1、standard-默認(rèn)模式
這個(gè)模式是默認(rèn)的啟動模式,即標(biāo)準(zhǔn)模式,在不指定啟動模式的前提下,系統(tǒng)默認(rèn)使用該模式啟動Activity,每次啟動一個(gè)Activity都會重寫創(chuàng)建一個(gè)新的實(shí)例,不管這個(gè)實(shí)例存不存在,這種模式下,誰啟動了該模式的Activity,該Activity就屬于啟動它的Activity的任務(wù)棧中。這個(gè)Activity它的onCreate(),onStart(),onResume()方法都會被調(diào)用。
配置模式
<activity
android:name=".StandardActivity"
android:launchMode="standard">
</activity>
點(diǎn)擊啟動
啟動了MainActivity頁面之后,出現(xiàn)如下:
點(diǎn)擊 第一個(gè) 按鈕,
進(jìn)入 StandardActivity 頁面
點(diǎn)擊 啟動標(biāo)準(zhǔn)ACT 按鈕,新啟頁面,新啟動頁面又點(diǎn)擊
輸出日志
1340-1340/com.godfather.actluanchmodeltest D/BaseActivity: onCreate: MainActivity hashCode:77616355 taskId:9298
1340-1340/com.godfather.actluanchmodeltest D/BaseActivity: dumpTaskAffinity: taskAffinity = com.godfather.actluanchmodeltest
1340-1340/com.godfather.actluanchmodeltest D/BaseActivity: onCreate: StandardActivity hashCode:208435735 taskId:9298
1340-1340/com.godfather.actluanchmodeltest D/BaseActivity: dumpTaskAffinity: taskAffinity = com.godfather.actluanchmodeltest
1340-1340/com.godfather.actluanchmodeltest D/BaseActivity: onCreate: StandardActivity hashCode:197794590 taskId:9298
1340-1340/com.godfather.actluanchmodeltest D/BaseActivity: dumpTaskAffinity: taskAffinity = com.godfather.actluanchmodeltest
1340-1340/com.godfather.actluanchmodeltest D/BaseActivity: onCreate: StandardActivity hashCode:210232075 taskId:9298
1340-1340/com.godfather.actluanchmodeltest D/BaseActivity: dumpTaskAffinity: taskAffinity = com.godfather.actluanchmodeltest
案例分析:
MainActivity 啟動,新建了一個(gè)TASK任務(wù)棧,ID為:9298
之后每次新建的頁面 TASK ID 都是 9298,印證了 “誰啟動了該模式的Activity,該Activity就屬于啟動它的Activity的任務(wù)棧中” ,并且每次的hashCode都是不一樣的,說明了是不同的實(shí)例。
2、singleTop-棧頂復(fù)用模式
側(cè)重:棧頂存在,才復(fù)用
配置形式
<activity
android:name=".SingleTopActivity"
android:launchMode="singleTop"
/>
啟動了MainActivity頁面之后,出現(xiàn)如下:
點(diǎn)擊 第二個(gè) 按鈕, 進(jìn)入singleTopActivity
日志
26718-26718/com.godfather.actluanchmodeltest D/BaseActivity: onCreate: MainActivity hashCode:77616355 taskId:9304
26718-26718/com.godfather.actluanchmodeltest D/BaseActivity: dumpTaskAffinity: taskAffinity = com.godfather.actluanchmodeltest
26718-26718/com.godfather.actluanchmodeltest D/BaseActivity: onCreate: SingleTopActivity hashCode:138919517 taskId:9304
26718-26718/com.godfather.actluanchmodeltest D/BaseActivity: dumpTaskAffinity: taskAffinity = com.godfather.actluanchmodeltest
26718-26718/com.godfather.actluanchmodeltest D/BaseActivity: onNewIntent: SingleTopActivity hashCode:138919517 taskId:9304
26718-26718/com.godfather.actluanchmodeltest D/BaseActivity: dumpTaskAffinity: taskAffinity = com.godfather.actluanchmodeltest
26718-26718/com.godfather.actluanchmodeltest D/BaseActivity: onNewIntent: SingleTopActivity hashCode:138919517 taskId:9304
26718-26718/com.godfather.actluanchmodeltest D/BaseActivity: dumpTaskAffinity: taskAffinity = com.godfather.actluanchmodeltest
案例分析
以SingleTop方式啟動的Activity,
當(dāng)實(shí)例存在的情況下:
1、activity存在,并且在棧頂:每次只會執(zhí)行onNewIntent方法,它會復(fù)用已經(jīng)存在的實(shí)例。
并且每次的hashCode都是相同的。
2、activity存在,但是不在棧頂,我們測試一下:
先點(diǎn)擊 啟動其他Activity
其他Activity頁面如下:
點(diǎn)擊啟動SingleTopActivty
日志
可以看到,singletopActivity 被重新創(chuàng)建,并沒有復(fù)用。
singleTop模式分3種情況
- 當(dāng)前棧中已有該Activity的實(shí)例并且該實(shí)例位于棧頂時(shí),不會新建實(shí)例,而是復(fù)用棧頂?shù)膶?shí)例,并且會將Intent對象傳入,回調(diào)onNewIntent方法
- 當(dāng)前棧中已有該Activity的實(shí)例但是該實(shí)例不在棧頂時(shí),其行為和standard啟動模式一樣,依然會創(chuàng)建一個(gè)新的實(shí)例
- 當(dāng)前棧中不存在該Activity的實(shí)例時(shí),其行為同standard啟動模式
standard和singleTop啟動模式都是在原任務(wù)棧中新建Activity實(shí)例,不會啟動新的Task,即使你指定了taskAffinity屬性。
那么什么是taskAffinity屬性呢,可以簡單的理解為任務(wù)相關(guān)性。
- 這個(gè)參數(shù)標(biāo)識了一個(gè)Activity所需任務(wù)棧的名字,默認(rèn)情況下,所有Activity所需的任務(wù)棧的名字為應(yīng)用的包名
- 我們可以單獨(dú)指定每一個(gè)Activity的taskAffinity屬性覆蓋默認(rèn)值
- 一個(gè)任務(wù)的affinity決定于這個(gè)任務(wù)的根activity(root activity)的taskAffinity
- 在概念上,具有相同的affinity的activity(即設(shè)置了相同taskAffinity屬性的activity)屬于同一個(gè)任務(wù)
- 為一個(gè)activity的taskAffinity設(shè)置一個(gè)空字符串,表明這個(gè)activity不屬于任何task
很重要的一點(diǎn)taskAffinity屬性不對standard和singleTop模式有任何影響,即時(shí)你指定了該屬性為其他不同的值,這兩種啟動模式下不會創(chuàng)建新的task(如果不指定即默認(rèn)值,即包名)
3、singleTask-棧內(nèi)復(fù)用模式
側(cè)重:存在就復(fù)用
這種模式相對復(fù)雜,它主要側(cè)重在任何情況下的復(fù)用,不管實(shí)例是否在棧頂,如果不在棧頂,則會將它上面的全部act出棧,自己成為棧頂act,并回調(diào)onNewInent方法,其實(shí)呢,這個(gè)過程它需要匹配自己的任務(wù)棧,通過taskAffinity屬性指定,如果這個(gè)標(biāo)識的任務(wù)棧不存在,則創(chuàng)建,不過一般不需要使用這個(gè)屬性!
配置形式
<activity
android:name=".SingleTaskActivity"
android:launchMode="singleTask" />
進(jìn)入SingleTaskActivity頁面
1、點(diǎn)擊啟動自己
日志:
可以發(fā)現(xiàn),每次都是復(fù)用自己。
2、點(diǎn)擊 啟動其他頁面
點(diǎn)擊返回 SingleTaskActivity
日志:
可以發(fā)現(xiàn),復(fù)用了非棧頂?shù)膶?shí)例!!
并且將其他頁面(otherTaskActivity)出棧了(點(diǎn)擊底部導(dǎo)航欄返回按鈕,不能回到otherTaskActivity 頁面了。)
任務(wù)棧的act實(shí)例如圖:
也可以使用adb shell dumpsys activity activities 命令查看任務(wù)棧:
其實(shí)是這樣的,我們并沒有指定taskAffinity屬性,這說明和默認(rèn)值一樣,也就是包名,當(dāng)MainActivity啟動時(shí)創(chuàng)建的Task的名字就是包名,因?yàn)镸ainActivity也沒有指定taskAffinity,而當(dāng)我們啟動SingleTaskActivity ,首先會尋找需要的任務(wù)棧是否存在,也就是taskAffinity指定的值,這里就是包名,發(fā)現(xiàn)存在,就不再創(chuàng)建新的task,而是直接使用。當(dāng)該task中存在該Activity實(shí)例時(shí)就會復(fù)用該實(shí)例,這就是棧內(nèi)復(fù)用模式。
這時(shí)候,如果我們指定SingleTaskActivity 的taskAffinity值。
<activity
android:name=".SingleTaskActivity"
android:taskAffinity="com.godfather.actluanchmodeltest.singleTask"
android:launchMode="singleTask" />
<!-- android:taskAffinity="singleTask" 指定創(chuàng)建名字為 singnleTask的任務(wù)棧-->
日志
可以發(fā)現(xiàn),TaskID變了,并且OtherTaskActivity的TaskID 跟啟動它的activity所在taskID一致。“誰啟動了標(biāo)準(zhǔn)模式的Activity,該Activity就屬于啟動它的Activity的任務(wù)棧中”
結(jié)論
singleTask啟動模式啟動Activity時(shí),首先會根據(jù)taskAffinity去尋找當(dāng)前是否存在一個(gè)對應(yīng)名字的任務(wù)棧
- 如果不存在,則會創(chuàng)建一個(gè)新的Task,并創(chuàng)建新的Activity實(shí)例入棧到新創(chuàng)建的Task中去
- 如果存在,則得到該任務(wù)棧,查找該任務(wù)棧中是否存在該Activity實(shí)例
1、如果存在實(shí)例,則將它上面的Activity實(shí)例都出棧,然后回調(diào)啟動的Activity實(shí)例的onNewIntent方法
2、如果不存在該實(shí)例,則新建Activity,并入棧
此外,我們可以將兩個(gè)不同App中的Activity設(shè)置為相同的taskAffinity,這樣雖然在不同的應(yīng)用中,但是Activity會被分配到同一個(gè)Task中去。
4、singleInstance-全局唯一模式
側(cè)重:它具有singleTask 的全部特征之外,獨(dú)占一個(gè)任務(wù)棧,并且系統(tǒng)的全局唯一性!!
如果多個(gè)應(yīng)用啟動同一個(gè)activty頁面,則會在不用應(yīng)用之中可以復(fù)用這個(gè)頁面。執(zhí)行onNewIntent方法
點(diǎn)擊第四個(gè)按鈕
進(jìn)入SingleInstance頁面:
再點(diǎn)擊啟動OtherActivity
點(diǎn)擊啟動SingleInstance頁面
日志:
日志發(fā)現(xiàn),它啟動的時(shí)候,taskID跟MainActivity的不一樣,并且在SingleInstance頁面啟動的OtherActivity的TaskID 也是不與SingleInstanceActivity的相同!
說明SingleInstance是獨(dú)占任務(wù)棧的!
只要實(shí)例存在,就會復(fù)用,同時(shí)它具有SingleTask的全部特性!!
至此:Activity的四種啟動模式已經(jīng)講完。
開源代碼鏈接 : https://github.com/IDBAI/ActLuanchModelTest