Activity啓動模式launchMode
今天要講得是Activity的四種啓動模式launchMode屬性,該屬性用於配置該Activity的加載模式,該屬性支持以下4個屬性值。
- standard:標準模式,也是默認模式。
- singletop:Task棧頂單例模式。
- singleTask:Task內單例模式。
- singlestance:全局單例模式。
在繼續寫下去之前我想說一下,像launchMode這種基礎的Android知識在網上已經有很多大神寫得十分詳細,爲什麼我還要寫呢?我之所以寫,是因爲我確確實實是個菜鳥,將課本、網上大神的總結再加上自己對知識點的認知去寫出來希望讓我對這個知識點更加了解。
以下是參考的博客:
- http://blog.csdn.net/liuhe688/article/details/6754323
- http://www.cnblogs.com/lwbqqyumidi/p/3771542.html
以下是參考的書籍:
- 《瘋狂的Android講義》電子工業出版社
回到話題,今天要弄懂的是:
- 爲什麼要爲Activity指定加載模式?
- 每個加載模式有什麼不同?
- 在什麼時候應該用哪一種模式?
- 怎麼樣使用加載模式?
先介紹Android對Activity的管理,Android採用Task來管理多個Activity,當我們啓動一個應用是,Android就會爲其創建一個Task,然後啓動這個應用的入口Activity (即 < intent-filter…/>)中配置的MAIN和LAUNCHER)。
可以把Task理解爲任務棧,Task以棧的形式管理Activity:先入後出。通過調用Activity的getTaskId()的方法來獲取他所在Task的ID。
launchMode在多個Activity跳轉的過程中扮演着重要的角色,它可以決定是否生成新的Activity實例,是否重用已存在的Activity實例,是否和其他Activity實例共用一個Task。
那麼Activity的加載模式就是負責管理實例化,加載Activity的方式,並可以控制Activity與Task之間的加載關係。
首先我們可以在AndroidManifest.xml中配置Activity的 android:launchMode屬性:
<activity
android:name=".MainActivity"
android:launchMode="standard">
</activity>
接下來我們就開始認識這4種加載模式。
1.standard
每次通過這種模式啓動目標Activity時,Android總會爲其目標Activity創建一個新的實例,並將其添加到當前Task棧中,所有我們發現:是在同個任務棧裏面,只是創建了不同的實例。
下面示例使用standard模式不斷啓動自身:
public class MainActivity3 extends ActionBarActivity {
private TextView tv;
private Button btn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_activity3);
tv = (TextView) findViewById(R.id.tv);//定義文本
btn = (Button) findViewById(R.id.Btn);//定義按鈕
tv.setText(String.format("TaskId:%d\n Current Activity:%s", getTaskId(), toString()));
btn.setOnClickListener(new View.OnClickListener() {//爲按鈕添加監聽器,當單擊按鈕時啓動MainActivity3
@Override
public void onClick(View v) {
startActivity(new Intent(MainActivity3.this,MainActivity3.class));
}
});
}
正如以上代碼,每次單擊按鈕都會啓動自身MainActivity3,程序無需配置Activity的launchMode屬性,因爲默認是採用standard模式.
顯然,當用戶單擊手機上面的”返回”鍵時,系統會“逐一”從Activity棧頂刪除Activity實例。同時也表明這種加載模式不會使用全新的Task。
——————————
2.singleTop
我們先在AndroidManifest.xml中配置Activity的 android:launchMode屬性:
<activity
android:name=".MainActivity3"
android:launchMode="singleTop">
</activity>
這種模式與standard模式基本相同,但有一點是不同:當將要啓動的目標Activity已經位於Task棧頂時,系統不會重新創建目標Activity的實例。
使用的之前已修改啓動模式的實例:
當單擊按鈕時,並沒有什麼反應。
爲了更好的瞭解singleTop模式的作用,再創建一個Activity,MainActivity4。
現有MainActivity3、MainActivity4兩個Activity實例,功能是1.啓動自己,2.啓動另一個Activity。就好比A啓動A,A啓動B;B啓動A,B啓動B。
代碼只是多了個按鈕 以及監聽,這裏就不寫出來了
單擊上面那個按鈕就是A啓動A,在singleTop模式中是沒有反應的,當單擊下面那個按鈕時候就相當於 A啓動B,此時我們來看看反應如何:
根據上圖顯示,我們以及跳轉到了MainActivity4中,也就是我所說的B中, TaskId仍然與A中的12是一樣的,但兩個MainActivity實例是不一樣的。
此時我們再單擊第一個按鈕,也就是說由B到A,
此時我們仔細看,MainActivity3的兩次的實例都不一樣。
就想之前所說 :當將要啓動的目標Activity已經位於Task棧頂時,系統不會重新創建目標Activity的實例。而每次啓動其他的目標Activity時,功能就像standard模式。
——————————
3.singleTask
先在AndroidManifest.xml中配置Activity的 android:launchMode屬性:
<activity
android:name=".MainActivity3"
android:launchMode="singleTask">
</activity>
這個十分好理解,採用這種加載模式的Activity在同一個Task內只有一個實例,當系統採用singleTask模式啓動目標Activity時,分爲三種情況:
- 如果將要啓動的目標Activity 不存在,系統將會創建目標Activity的實例,並加入Task任務棧頂。
- 如果將要啓動的目標Activity 已經位於Task棧頂,此時與singleTop模式的行爲相同。
- 如果要啓動的Activity 已經存在、但沒有位於Task棧頂,系統會將把位於該Activity上面所有Activity移出Task,從而使其轉入棧頂 (大爺作風)。
——————————
4.singlelnstance
在AndroidManifest.xml中配置Activity的 android:launchMode屬性:
<activity
android:name=".MainActivity3"
android:launchMode="singlelnstance">
</activity>
在這種加載模式下,系統保證無論從哪個Task中啓動目標Activity,只會創建一個目標Activity實例,並會使用一個全新的Task棧來加載該Activity實例。
- 如果將要啓動的目標Activity 不存在,系統會先創建一個全新的Task棧,再創建目標Activity實例,並將它假如新的Task棧頂。
- 如果將要啓動的目標Activity 已經存在,無論它位於哪個應用程序中、位於哪個Task中,系統都會把該Activity所在的Task轉到前臺,從而使該Activity顯示出來。
——————————
合抱之木,生於毫末;九層之臺,起於累土;千里之行,始於足下。《老子》
作爲一個程序員,樹立遠大的目標是值得欣賞的,但不能只去空想,要一步一步地實踐纔行。成大事者,須從小事做起;萬事起於忽微,量變引起質變。 —— by @liuhe688