Activity 的啓動模式都有哪些以及各自的特點

Activity 的啓動模式都有哪些以及各自的特點
啓動模式(launchMode) 在多個 Activity 跳轉的過程中扮演着重要的角色, 它可以決定是否生成新的 Activity 實例,
是否重用已存在的 Activity 實例,是否和其他 Activity 實例公用一個 task 裏。這裏簡單介紹一下 task 的概念,task 
一個具有棧結構的對象,一個 task 可以管理多個 Activity,啓動一個應用,也就創建一個與之對應的 task
Activity 一共有以下四種 launchMode
1.standard
2.singleTop
3.singleTask
4.singleInstance
我們可以在 AndroidManifest.xml 配置<activity>的 android:launchMode 屬性爲以上四種之一即可。

下面我們結合實例一一介紹這四種 lanchMode:

1 standard
standard 模式是默認的啓動模式,不用爲<activity>配置 android:launchMode 屬性即可,當然也可以指定值
爲 standard。
我們將創建一個 Activity,命名爲 FirstActivity,來演示一下標準的啓動模式。FirstActivity 代碼如下:
public class FirstActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.first);
TextView textView = (TextView) findViewById(R.id.tv);
textView.setText(this.toString());
Button button = (Button) findViewById(R.id.bt);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(FirstActivity.this,
FirstActivity.class);
startActivity(intent);
}
});
}
}
FirstActivity 界面中的 TextView 用於顯示當前 Activity 實例的序列號, Button 用於跳轉到下一個 FirstActivity 界面。
然後我們連續點擊幾次按鈕,將會出現下面的現象:



我們注意到都是 FirstActivity 的實例, 但序列號不同, 並且我們需要連續按後退鍵兩次, 才能回到第一個 FirstActivity。
standard 模式的原理如下圖所示:
如圖所示,每次跳轉系統都會在 task 中生成一個新的 FirstActivity 實例,並且放於棧結構的頂部,當我們按下後退鍵
時,才能看到原來的 FirstActivity 實例。
這就是 standard 啓動模式,不管有沒有已存在的實例,都生成新的實例。



2 singleTop
我們在上面的基礎上爲<activity>指定屬性 android:launchMode="singleTop",系統就會按照 singleTop 啓
動模式處理跳轉行爲。我們重複上面幾個動作,將會出現下面的現象:

我們看到這個結果跟 standard 有所不同,三個序列號是相同的,也就是說使用的都是同一個 FirstActivity 實例;
如果按一下後退鍵,程序立即退出,說明當前棧結構中只有一個 Activity 實例。singleTop 模式的原理如下圖所示:
正如上圖所示,跳轉時系統會先在棧結構中尋找是否有一個 FirstActivity 實例正位於棧頂,如果有則不再生成新的,
而是直接使用。也許朋友們會有疑問,我只看到棧內只有一個 Activity,如果是多個 Activity 怎麼辦,如果不是在棧
頂會如何?我們接下來再通過一個示例來證實一下大家的疑問。
我們再新建一個 Activity 命名爲 SecondActivity,如下:

public class SecondActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.second);
TextView textView = (TextView) findViewById(R.id.tv);
textView.setText(this.toString());
Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(SecondActivity.this,
FirstActivity.class);
startActivity(intent);
}
});
}
}
然後將之前的 FirstActivity 跳轉代碼改爲:
Intent intent = new Intent(FirstActivity.this, SecondActivity.clas
s);
startActivity(intent);
這時候,FirstActivity 會跳轉到 SecondActivity,SecondActivity 又會跳轉到 FirstActivity。演示結果如下:

我們看到,兩個 FirstActivity 的序列號是不同的,證明從 SecondActivity 跳轉到 FirstActivity 時生成了新的
FirstActivity 實例。原理圖如下:
我們看到,當從 SecondActivity 跳轉到 FirstActivity 時,系統發現存在有 FirstActivity 實例,但不是位於棧頂,
於是重新生成一個實例。
這就是 singleTop 啓動模式,如果發現有對應的 Activity 實例正位於棧頂,則重複利用,不再生成新的實例。

3 singleTask
在上面的基礎上我們修改 FirstActivity 的屬性 android:launchMode="singleTask"。演示的結果如下:

我們注意到,在上面的過程中,FirstActivity 的序列號是不變的,SecondActivity 的序列號卻不是唯一的,說明
從 SecondActivity 跳轉到 FirstActivity 時,沒有生成新的實例,但是從 FirstActivity 跳轉到 SecondActivity 時生成
了新的實例。singleTask 模式的原理圖如下圖所示:
在圖中的下半部分是 SecondActivity 跳轉到 FirstActivity 後的棧結構變化的結果,我們注意到,SecondActivity
消失了,沒錯,在這個跳轉過程中系統發現有存在的 FirstActivity 實例,於是不再生成新的實例,而是將 FirstActivity
之上的 Activity 實例統統出棧, 將 FirstActivity 變爲棧頂對象, 顯示到幕前。 也許朋友們有疑問, 如果將 SecondActivity
也設置爲 singleTask 模式,那麼 SecondActivity 實例是不是可以唯一呢?在我們這個示例中是不可能的,因爲每次
從 SecondActivity 跳轉到 FirstActivity 時,SecondActivity 實例都被迫出棧,下次等 FirstActivity 跳轉到SecondActivity 時,找不到存在的 SecondActivity 實例,於是必鬚生成新的實例。但是如果我們有 ThirdActivity,
讓 SecondActivity 和 ThirdActivity 互相跳轉,那麼 SecondActivity 實例就可以保證唯一。
這就是 singleTask 模式,如果發現有對應的 Activity 實例,則使此 Activity 實例之上的其他 Activity 實例統統出
棧,使此 Activity 實例成爲棧頂對象,顯示到幕前。

4 singleInstance
這種啓動模式比較特殊,因爲它會啓用一個新的棧結構,將 Activity 放置於這個新的棧結構中,並保證不再有其
他 Activity 實例進入。
我們修改 FirstActivity 的 launchMode="standard",SecondActivity 的 launchMode="singleInstance",由
於涉及到了多個棧結構,我們需要在每個 Activity 中顯示當前棧結構的 id,所以我們爲每個 Activity 添加如下代碼:
TextView taskIdView = (TextView) findViewById(R.id.taskIdView);
taskIdView.setText("current task id: " this.getTaskId());
然後我們再演示一下這個流程:

我們發現這兩個 Activity 實例分別被放置在不同的棧結構中,關於 singleInstance 的原理圖如下
我們看到從 FirstActivity 跳轉到 SecondActivity 時,重新啓用了一個新的棧結構,來放置 SecondActivity 實例,
然後按下後退鍵,再次回到原始棧結構;圖中下半部分顯示的在 SecondActivity 中再次跳轉到 FirstActivity,這個時
候系統會在原始棧結構中生成一個 FirstActivity 實例, 然後回退兩次, 注意, 並沒有退出, 而是回到了 SecondActivity,
爲什麼呢?是因爲從 SecondActivity 跳轉到 FirstActivity 的時候,我們的起點變成了 SecondActivity 實例所在的棧
結構,這樣一來,我們需要“迴歸”到這個棧結構。
如果我們修改 FirstActivity 的 launchMode 值爲 singleTop、singleTask、singleInstance 中的任意一個,流程將會
如圖所示:

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