天天看點

Android中Activity四種啟動方式

一,任務棧的了解

參考自:https://developer.android.com/guide/components/tasks-and-back-stack.html

1.閑扯兩句

一個Android應用是包含若幹個Activity的,每個 Activity 均圍繞使用者可以執行的特定操作設計,并且能夠啟動其他 Activity。 這些Activity之間可以借助Intent進行跳轉,這些跳轉的發起點一般也是Activity。例如,電子郵件應用可能有一個 Activity 顯示新郵件的清單。使用者選擇某郵件時,會打開一個新 Activity 以檢視該郵件。

想象一個場景,某一個應用因為實際需求包含了很多的Activity,Activity在代碼層次上就是一個Java類,每啟動一個Activity,其實就是建立一個執行個體或者說将背景的執行個體拿到前台運作。這個過程中,啟動一個Activity是需要時間的,并且一個Activity從建立–>可見–>可互動,然後還會有一個資料的初始化過程,肯定是需要一定的時間的,如果這些Activity沒有一個合适的資料結構去組織,再想要達到一個好的使用體驗是很困難了。

2.Android系統對Activity的組織結構

Android中Activity四種啟動方式

 考慮下上圖這個啟動的流程,當應用啟動了Activity1之後,Activity1又啟動了Activity2,Activity2又啟動了Activity3,那麼我們進行傳回操作的時候,當然是回退到最後一幅圖的狀态。這樣的資料結構就是一個棧的形式:“後進先出”。這樣的結構對一般的依次啟動,鍊式的跳轉下一個Activity,正常的傳回上一個Activity自然是可以勝任的。但是如果這樣,在第三張圖中,Activity3要啟動Activity1,這種狀态處理?

(1).将Activity1上面的兩個Activity都pop出去,然後Activity1處于棧頂,通過系統回調方法的執行就可以再次恢複

(2).重新建立一個新的Activity1執行個體,然後onCreate()–>onStart()–>onResume()進行

(3).重新開一個新的棧,建立一個Activity1,然後onCreate()–>onStart()–>onResume()

dang,需要是一直在變的,早晚都會有這樣那樣的需求的,那麼類似這些情況怎麼去處理呢?

二,Activity的四種啟動模式

哪四種?各有什麼特征?

(1)standard 标準模式

隻要建立了Activity執行個體,一旦激活該Activity,則會向任務棧中加入新的建立的執行個體,退出Activity就會在任務棧中銷毀該執行個體。

(2)singleTop 棧頂複用

這種模式會在目前要激活的Activity執行個體是否在任務棧頂,如果處于棧頂則不再重新建立新的執行個體,會重用已存在的執行個體,否則會在任務中建立新的執行個體。

(3)singleTask 棧内複用

對比singleTop模式,如果将要激活的Activity已經存在任務棧中了,則将該任務棧中該執行個體以上的Activity執行個體全部出棧,然後調用該執行個體的newIntance()方法重用該Activity,使該執行個體處于棧頂位置,否則就重新建立一個新的Activity執行個體。

(4)singleInstance 全局單例

當該模式的Activity執行個體在任務棧中被建立後,隻要該執行個體還在任務棧中,即隻要激活的是該類型的Activity,都會通過調用該執行個體的newInstance()方法重用該Activity,此時使用的都是同一個Activity執行個體,它都會處于任務棧的棧頂。

google官網的表格總結:

Android中Activity四種啟動方式

怎麼設定launchMode?

  • 在Manifest.xml檔案中,用launchmode屬性設定Activity的啟動模式:
<activity
            android:name=".MainActivity"
            android:configChanges="orientation|keyboardHidden"
            android:label="@string/app_name"
            android:windowSoftInputMode="adjustUnspecified|stateHidden"
            android:launchMode="standard|singleTop|singleInstance|singleTask">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>

                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
           
  • 通過在Intent中設定标記位指定launchMode
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
           
  • 啟動模式和标記位的對應關系:
    • FLAG_ACTIVITY_NEW_TASK -> singleTask
    • FLAG_ACTIVITY_SINGLE_TOP -> singleTop
    • FLAG_ACTIVITY_CLEAR_TOP : 同一個任務棧中位于它上面的Activity都要出棧
    • FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS -> android:excludeFromRecents