-
Activity為什么需要啟動模式?
為了避免頻繁啟動一個Activity時,生成多個實例,杜絕內(nèi)存浪費。
一個Activity啟動時,這個Activity實例就會被放入任務(wù)棧(Task)中; 當(dāng)點擊返回鍵的時候,位于任務(wù)棧頂層的Activity就會被清理出去; 當(dāng)任務(wù)棧中不存在任何Activity實例后,系統(tǒng)就會去回收這個任務(wù)棧,程序退出。 -
怎么用
1.通過AndroidMenifest.xml文件為Activity指定啟動模式
<activity android:name=".activity" android:launchMode="standard" />2.通過在Intent中設(shè)置標(biāo)志位(addFlags方法)來為Activity指定啟動模式
Intent intent = new Intent(); intent.setClass(ActivityB.this,ActivityA.class); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent);常用的Activity的Flag
-
Intent.FLAG_ACTIVITY_NEW_TASK
相當(dāng)于singleTask 通常我們在Service啟動Activity時由于Service中并沒有Activity任務(wù)棧, 所以必須使用該Flag來創(chuàng)建一個新的Task.-
Intent.FLAG_ACTIVITY_SINGLE_TOP
該標(biāo)志位表示使用singleTop模式來啟動一個Activity-
Intent.FLAG_ACTIVITY_CLEAR_TOP
該標(biāo)志位表示使用singleTask模式來啟動一個Activity-
Intent.FLAG_ACTIVITY_NO_HISTORY
使用該模式來啟動Activity,當(dāng)該Activity啟動其他Activity后, 該Activity就被銷毀了,不會保留在任務(wù)棧中。 如A-B,B中以這種模式啟動C,C再啟動D,則任務(wù)棧只有ABD。-
Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
使用該標(biāo)識位啟動的Activity不添加到最近應(yīng)用列表, 也即我們從最近應(yīng)用里面查看不到我們啟動的這個activity。 與屬性android:excludeFromRecents="true"效果相同。 -
-
taskAffinity 屬性
taskAffinity屬性不對standard和singleTop模式有任何影響
<activity android:name=".ActivitySingleTop" android:launchMode="singleTop" android:taskAffinity="com.castiel.demo.singletop"/>- 這個參數(shù)標(biāo)示了一個Activity所需任務(wù)棧的名字,默認(rèn)情況下,所有Activity所需的任務(wù)棧的名字為應(yīng)用包名
- 一個任務(wù)的affinity決定于這個任務(wù)的根activity的taskAffinity
- 具有相同的affinity的activity(即設(shè)置了相同taskAffinity屬 性的activity)屬于同一個任務(wù)
- 為一個activity的taskAffinity設(shè)置一個空字符串,表明這個activity不屬于任何task;
-
Activity的4種啟動模式
-
standard-默認(rèn)模式
允許多個相同Activity實例創(chuàng)建,疊加;
-
singleTop-棧頂復(fù)用模式
如果新的activity已經(jīng)位于棧頂,那么這個activity不會被重寫創(chuàng)建,同時它的onNewIntent方法會被調(diào)用,通過此方法的參數(shù)可以去除當(dāng)前請求的信息;
如果棧頂不存在該activity的實例,則情況與standard模式相同;
-
singleTask-棧內(nèi)復(fù)用模式
模式啟動時會通過taskAffinity屬性尋找任務(wù)棧,如果任務(wù)棧不存在,最會創(chuàng)建這個任務(wù)棧
如果棧中存在這個Activity的實例就會復(fù)用這個Activity,復(fù)用時,會將它上面的Activity出棧,并調(diào)用該實例的onNewIntent
-
singleInstance-全局唯一模式
該模式具備singleTask模式的所有特性外
區(qū)別:這種模式下Activity會單獨占用一個Task棧,具有全局唯一性(即整個系統(tǒng)中就這么一個實例),除非這個任務(wù)棧銷毀,否則不會創(chuàng)建新的實例
-
應(yīng)用場景
standard:普通activity
singleTop:適合接收通知啟動的內(nèi)容顯示頁面
比如一下子收到一堆推送消息,不能每個都彈出來吧。但凡是這樣的都行。優(yōu)酷的推薦視頻,電商app推送一個活動。
singleTask:程序入口等啟動頁面
最常見的應(yīng)用場景就是保持我們應(yīng)用開啟后僅僅有一個Activity的實例。最典型的樣例就是應(yīng)用中展示的主頁面(Fragment的containerActivity)、WebView頁面、掃一掃頁面、電商中:購物界面,確認(rèn)訂單界面,付款界面。
singleInstance:完全獨立的
系統(tǒng)Launcher、鎖屏鍵、來電顯示等系統(tǒng)應(yīng)用;
singleInstance不要用于中間頁面,如果用于中間頁面,跳轉(zhuǎn)會有問題。
問題:舉例 A -> B(singleInstance) ->C
情形 1:在 C 界面返回,會直接返回到 A,繼續(xù)在 A 界面返回(退出) 會 出現(xiàn) B(singleInstance) 界面。
情形 2:打開 C 界面 ,HOME 鍵應(yīng)用推到后臺再次返回應(yīng)用,在 C 界面返回到 A,繼續(xù)在 A 界面返回(退出),B被系統(tǒng)殺死不會再出現(xiàn)(設(shè)置taskAffinity屬性除外)。
singleInstance用于中間頁面的情形被面試官問到了,思路沒錯,回來試了下確實是這樣無意中發(fā)現(xiàn)了情形 2的情況需要進一步驗證原因,這里暫且不議。
LaunchMode與startActivityForResult() 的一些使用問題
在 5.0 之前 可能會遇到這種情況:
startActivityForResult方法啟動一個Activity,然后在onActivityResult()方法中可以接收到上個頁面的回傳值,但你有可能遇到過拿不到返回值的情況。
原因:在還沒有開始界面跳轉(zhuǎn)本身的onActivityResult被馬上被執(zhí)行了
官方注解標(biāo)示:
Android認(rèn)為不同的Task之間對這種要求返回結(jié)果的啟動方式會產(chǎn)生一些依賴(對Task),所以干脆簡單粗暴在跳轉(zhuǎn)前直接返回RESULT_CANCELED結(jié)果。
關(guān)系如下:

所以要注意5.0之前對啟動模式的使用
5.0之后沒有這類問題。