Activity的四種啓動模式

活動的啓動模式對你來說應該是個全新的概念, 在實際項目中我們應該根據特定的需求
爲每個活動指定恰當的啓動模式。啓動模式一共有四種,分別是 standard、singleTop、
singleTask 和 singleInstance,可以在 AndroidManifest.xml 中通過給標籤指定
android:launchMode屬性來選擇啓動模式。
模式一:standard
standard 是活動默認的啓動模式,在不進行顯式指定的情況下,所有活動都會自動使用
這種啓動模式。因此,到目前爲止我們寫過的所有活動都是使用的 standard模式。經過上一
節的學習,你已經知道了 Android 是使用返回棧來管理活動的,在 standard 模式(即默認情
況)下,每當啓動一個新的活動,它就會在返回棧中入棧,並處於棧頂的位置。對於使用
standard 模式的活動,系統不會在乎這個活動是否已經在返回棧中存在,每次啓動都會創建
該活動的一個新的實例。

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d("FirstActivity", this.toString());
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.first_layout);
Button button1 = (Button) findViewById(R.id.button_1);
button1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(FirstActivity.this, FirstActivity.class);
startActivity(intent);
}
});

返回棧示意圖
這裏寫圖片描述
通過上一個調用下一個

singleTop
可能在有些情況下,你會覺得 standard模式不太合理。活動明明已經在棧頂了,爲什麼
再次啓動的時候還要創建一個新的活動實例呢?彆着急, 這只是系統默認的一種啓動模式而
已,你完全可以根據自己的需要進行修改,比如說使用 singleTop 模式。當活動的啓動模式
指定爲 singleTop, 在啓動活動時如果發現返回棧的棧頂已經是該活動, 則認爲可以直接使用
它,不會再創建新的活動實例。
singleTask
singleTop 模式的原理示意圖,如圖所示。
這裏寫圖片描述
使用 singleTop 模式可以很好地解決重複創建棧頂活動的問題,但是正如你在上一節所看到的,如果該活動並沒有處於棧頂的位置,還是可能會創建多個活動實例的。那麼有沒有
什麼辦法可以讓某個活動在整個應用程序的上下文中只存在一個實例呢?這就要藉助
singleTask模式來實現了。當活動的啓動模式指定爲 singleTask,每次啓動該活動時系統首先
會在返回棧中檢查是否存在該活動的實例,如果發現已經存在則直接使用該實例,並把在這
個活動之上的所有活動統統出棧,如果沒有發現就會創建一個新的活動實例。
我們還是通過代碼來更加直觀地理解一下。修改 AndroidManifest.xml 中 FirstActivity的
啓動模式:

<activity
android:name=".FirstActivity"
android:launchMode="singleTask"
android:label="This is FirstActivity" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

然後在 FirstActivity中添加 onRestart()方法,並打印日誌:

@Override
protected void onRestart() {
super.onRestart();
Log.d("FirstActivity", "onRestart");
}
最後在 SecondActivity中添加 onDestroy()方法,並打印日誌:
@Override
protected void onDestroy() {
super.onDestroy();
Log.d("SecondActivity", "onDestroy");
}

現在重新運行程序,在 FirstActivity 界面點擊按鈕進入到 SecondActivity,然後在
SecondActivity界面點擊按鈕,又會重新進入到 FirstActivity。
運行結果:

這裏寫圖片描述
使用singleTask的時候,當棧中有對象的實例了,android虛擬機就會把該實例前棧中的所有Activity進行onDestroy()方法將其銷燬

singleInstance
singleInstance 模式應該算是四種啓動模式中最特殊也最複雜的一個了, 你也需要多花點
功夫來理解這個模式。 不同於以上三種啓動模式, 指定爲 singleInstance 模式的活動會啓用一
個新的返回棧來管理這個活動(其實如果 singleTask模式指定了不同的 taskAffinity,也會啓動一個新的返回棧) 。那麼這樣做有什麼意義呢?想象以下場景,假設我們的程序中有一個
活動是允許其他程序調用的, 如果我們想實現其他程序和我們的程序可以共享這個活動的實
例,應該如何實現呢?使用前面三種啓動模式肯定是做不到的,因爲每個應用程序都會有自
己的返回棧,同一個活動在不同的返回棧中入棧時必然是創建了新的實例。而使用
singleInstance 模式就可以解決這個問題, 在這種模式下會有一個單獨的返回棧來管理這個活
動,不管是哪個應用程序來訪問這個活動,都共用的同一個返回棧,也就解決了共享活動實
例的問題。

可以看到,SecondActivity 的 Task id 不同於 FirstActivity 和 ThirdActivity,這說明
SecondActivity確實是存放在一個單獨的返回棧裏的, 而且這個棧中只有 SecondActivity這一
個活動。
然後我們按下 Back鍵進行返回, 你會發現 ThirdActivity竟然直接返回到了 FirstActivity,
再按下 Back 鍵又會返回到 SecondActivity,再按下 Back鍵纔會退出程序,這是爲什麼呢?
其實原理很簡單,由於 FirstActivity 和 ThirdActivity 是存放在同一個返回棧裏的,當在
ThirdActivity的界面按下 Back 鍵,ThirdActivity會從返回棧中出棧,那麼 FirstActivity 就成
爲了棧頂活動顯示在界面上,因此也就出現了從 ThirdActivity 直接返回到 FirstActivity 的情
況。然後在 FirstActivity界面再次按下 Back鍵,這時當前的返回棧已經空了,於是就顯示了
另一個返回棧的棧頂活動,即 SecondActivity。最後再次按下 Back 鍵,這時所有返回棧都已
經空了,也就自然退出了程序。
這裏寫圖片描述

“A task is a collection of activities that users interact with when performing a certain job. The activities are arranged in a stack (the “back stack”), in theorder in which each activity is opened.” 這是官網的定義。Task 是一組執行特定工作的Activity集合。執行一系列特定的動作,最後表現的效果就是一個任務,符合“任務”的解釋。Task 本質是集合,那麼承載這些的特定動作的就是back stack.這些Activity 在棧中按照執行順序排隊,壓盞出棧。
Lancher 是大部分任務的起點,當我們點擊應用程序圖標時,該程序的Task 就會被調至前臺開始運行。當應用程序是第一次打開,那麼就新建一個任務,將當前Application 的Main入口Activity 作爲root Activity 壓棧。如果該Activity 啓動了其他的Activity ,則new Activity 就會被壓棧,此時它在棧頂位置,並且獲取焦點。原來的Activity 在棧底,進入停止狀態,此時的停止並不是Activity的生命週期的onStop。當按下Back 鍵,當前棧定的Activity 出棧操作,被銷燬,之前停止的Activity 處在棧頂,重新獲取焦點。繼續按back ,程序就會一直退出,直到stack 空,任務被銷燬,返回到Lanucher.
這就是最普通的單個Task 管理Activity 的方式。但是我們在真正的開發中,由於良好交互的需要,多個頁面之間的跳轉並不是都嚴格按照這個規則執行,也達不到節省系統資源的目的。所以,Task 中Activity 的管理,給出了幾種特殊的模式,雖然Activity 在棧中的順序不能改變,但我們可以通過其他輔助手段,來改變這個規則。
1.”standard” (the default mode)
系統在Task 中創建由它當前啓動的Activity 的一個實例,並保存啓動它的Intent.該Activity 可以被實例化多次,每個實例可以屬於不同的Task,同一個Task 中也可以存在多個實例。也就是,實例之間是獨立的,每次啓動他都是產生一個新的實例。
2.”singleTop”
按照字面意思來理解,即在棧頂前2位置的Activity 實例不能相同。eg:A-B-C-D ,此時如果intent 要啓動D,那麼會通過onNewIntent(),到達之前當前的棧頂D,不會如standard 模式出現A-B-C-D-D,而還是A-B-C-D。注意:當一個新Activity 實例被創建,user 可通過back 返回前一個Activity.但是,如果是當前已經存在的Activity 實例handle a new intent.比如A-B-C-D,D-D情況下,在D 中,當a new intent 到onNewIntent()達前,back 是不能返回的。
3.”singleTask”
Activity 實例在一個單獨的Task 中,當再次啓動該Activity時,如果已經有一個實例,還是通過onNewIntent()定位到已經存在的實例,不重新創建。當前時間,Task中僅存在一個實例。由該Activity 啓動的Activity 實例都存在與同一個Task 中。
4.”singleInstance”
與singleTask 不同之處,當啓動其他Activity時,會爲後者單獨創建一個Task.

同樣也可以在Intent中設置Flag 達到上述部分模式相同的效果。
FLAG_ACTIVITY_NEW_TASK 同”singleTask”
FLAG_ACTIVITY_SINGLE_TOP 同 “singleTop”
FLAG_ACTIVITY_CLEAR_TOP 是比較特殊的,上面沒有相關模式與之對應。

FLAG_ACTIVITY_CLEAR_TOP
通俗的講,當要啓動一個已經存在與Stack 中的Activity 實例,如果該實例不在棧頂,則將在它之前的實例全部都Destory 掉,之後該實例順利登頂,運行。
通常和FLAG_ACTIVITY_NEW_TASK 一起用,用來定位一個已經在其他Task 中存在的Activity.或者將其放在指定位置,在特殊的時候,能夠響應Intent.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章