1政敢、standard-默認(rèn)模式
這個(gè)模式是默認(rèn)的啟動(dòng)模式,即標(biāo)準(zhǔn)模式谱煤,在不指定啟動(dòng)模式的前提下,系統(tǒng)默認(rèn)使用該模式啟動(dòng)Activity嘉抓,每次啟動(dòng)一個(gè)Activity都會(huì)重寫(xiě)創(chuàng)建一個(gè)新的實(shí)例索守,不管這個(gè)實(shí)例存不存在,這種模式下掌眠,誰(shuí)啟動(dòng)了該模式的Activity蕾盯,該Activity就屬于啟動(dòng)它的Activity的任務(wù)棧中。這個(gè)Activity它的onCreate()蓝丙,onStart(),onResume()方法都會(huì)被調(diào)用望拖。
配置模式
<activity
android:name=".StandardActivity"
android:launchMode="standard">
</activity>
點(diǎn)擊啟動(dòng)
啟動(dòng)了MainActivity頁(yè)面之后渺尘,出現(xiàn)如下:
點(diǎn)擊 第一個(gè) 按鈕,
進(jìn)入 StandardActivity 頁(yè)面
點(diǎn)擊 啟動(dòng)標(biāo)準(zhǔn)ACT 按鈕说敏,新啟頁(yè)面鸥跟,新啟動(dòng)頁(yè)面又點(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 啟動(dòng),新建了一個(gè)TASK任務(wù)棧盔沫,ID為:9298
之后每次新建的頁(yè)面 TASK ID 都是 9298医咨,印證了 “誰(shuí)啟動(dòng)了該模式的Activity,該Activity就屬于啟動(dòng)它的Activity的任務(wù)棧中” 架诞,并且每次的hashCode都是不一樣的拟淮,說(shuō)明了是不同的實(shí)例。
2谴忧、singleTop-棧頂復(fù)用模式
側(cè)重:棧頂存在很泊,才復(fù)用
配置形式
<activity
android:name=".SingleTopActivity"
android:launchMode="singleTop"
/>
啟動(dòng)了MainActivity頁(yè)面之后,出現(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方式啟動(dòng)的Activity委造,
當(dāng)實(shí)例存在的情況下:
1、activity存在均驶,并且在棧頂:每次只會(huì)執(zhí)行onNewIntent方法昏兆,它會(huì)復(fù)用已經(jīng)存在的實(shí)例。
并且每次的hashCode都是相同的妇穴。
2爬虱、activity存在,但是不在棧頂伟骨,我們測(cè)試一下:
先點(diǎn)擊 啟動(dòng)其他Activity
其他Activity頁(yè)面如下:
點(diǎn)擊啟動(dòng)SingleTopActivty
日志
可以看到饮潦,singletopActivity 被重新創(chuàng)建,并沒(méi)有復(fù)用携狭。
singleTop模式分3種情況
- 當(dāng)前棧中已有該Activity的實(shí)例并且該實(shí)例位于棧頂時(shí)继蜡,不會(huì)新建實(shí)例,而是復(fù)用棧頂?shù)膶?shí)例,并且會(huì)將Intent對(duì)象傳入稀并,回調(diào)onNewIntent方法
- 當(dāng)前棧中已有該Activity的實(shí)例但是該實(shí)例不在棧頂時(shí)仅颇,其行為和standard啟動(dòng)模式一樣,依然會(huì)創(chuàng)建一個(gè)新的實(shí)例
- 當(dāng)前棧中不存在該Activity的實(shí)例時(shí)碘举,其行為同standard啟動(dòng)模式
standard和singleTop啟動(dòng)模式都是在原任務(wù)棧中新建Activity實(shí)例忘瓦,不會(huì)啟動(dòng)新的Task,即使你指定了taskAffinity屬性引颈。
那么什么是taskAffinity屬性呢耕皮,可以簡(jiǎn)單的理解為任務(wù)相關(guān)性。
- 這個(gè)參數(shù)標(biāo)識(shí)了一個(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屬性不對(duì)standard和singleTop模式有任何影響罚拟,即時(shí)你指定了該屬性為其他不同的值,這兩種啟動(dòng)模式下不會(huì)創(chuàng)建新的task(如果不指定即默認(rèn)值完箩,即包名)
3赐俗、singleTask-棧內(nèi)復(fù)用模式
側(cè)重:存在就復(fù)用
這種模式相對(duì)復(fù)雜,它主要側(cè)重在任何情況下的復(fù)用弊知,不管實(shí)例是否在棧頂阻逮,如果不在棧頂,則會(huì)將它上面的全部act出棧吉捶,自己成為棧頂act夺鲜,并回調(diào)onNewInent方法,其實(shí)呢呐舔,這個(gè)過(guò)程它需要匹配自己的任務(wù)棧币励,通過(guò)taskAffinity屬性指定,如果這個(gè)標(biāo)識(shí)的任務(wù)棧不存在珊拼,則創(chuàng)建食呻,不過(guò)一般不需要使用這個(gè)屬性!
配置形式
<activity
android:name=".SingleTaskActivity"
android:launchMode="singleTask" />
進(jìn)入SingleTaskActivity頁(yè)面
1澎现、點(diǎn)擊啟動(dòng)自己
日志:
可以發(fā)現(xiàn)仅胞,每次都是復(fù)用自己。
2剑辫、點(diǎn)擊 啟動(dòng)其他頁(yè)面
點(diǎn)擊返回 SingleTaskActivity
日志:
可以發(fā)現(xiàn)干旧,復(fù)用了非棧頂?shù)膶?shí)例!妹蔽!
并且將其他頁(yè)面(otherTaskActivity)出棧了(點(diǎn)擊底部導(dǎo)航欄返回按鈕椎眯,不能回到otherTaskActivity 頁(yè)面了挠将。)
任務(wù)棧的act實(shí)例如圖:
也可以使用adb shell dumpsys activity activities 命令查看任務(wù)棧:
其實(shí)是這樣的,我們并沒(méi)有指定taskAffinity屬性编整,這說(shuō)明和默認(rèn)值一樣舔稀,也就是包名,當(dāng)MainActivity啟動(dòng)時(shí)創(chuàng)建的Task的名字就是包名掌测,因?yàn)镸ainActivity也沒(méi)有指定taskAffinity内贮,而當(dāng)我們啟動(dòng)SingleTaskActivity ,首先會(huì)尋找需要的任務(wù)棧是否存在汞斧,也就是taskAffinity指定的值夜郁,這里就是包名,發(fā)現(xiàn)存在粘勒,就不再創(chuàng)建新的task拂酣,而是直接使用。當(dāng)該task中存在該Activity實(shí)例時(shí)就會(huì)復(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 跟啟動(dòng)它的activity所在taskID一致暂刘。“誰(shuí)啟動(dòng)了標(biāo)準(zhǔn)模式的Activity,該Activity就屬于啟動(dòng)它的Activity的任務(wù)棧中”
結(jié)論
singleTask啟動(dòng)模式啟動(dòng)Activity時(shí)捂刺,首先會(huì)根據(jù)taskAffinity去尋找當(dāng)前是否存在一個(gè)對(duì)應(yīng)名字的任務(wù)棧
- 如果不存在谣拣,則會(huì)創(chuàng)建一個(gè)新的Task,并創(chuàng)建新的Activity實(shí)例入棧到新創(chuàng)建的Task中去
- 如果存在族展,則得到該任務(wù)棧森缠,查找該任務(wù)棧中是否存在該Activity實(shí)例
1、如果存在實(shí)例仪缸,則將它上面的Activity實(shí)例都出棧贵涵,然后回調(diào)啟動(dòng)的Activity實(shí)例的onNewIntent方法
2、如果不存在該實(shí)例恰画,則新建Activity宾茂,并入棧
此外,我們可以將兩個(gè)不同App中的Activity設(shè)置為相同的taskAffinity拴还,這樣雖然在不同的應(yīng)用中跨晴,但是Activity會(huì)被分配到同一個(gè)Task中去。
4片林、singleInstance-全局唯一模式
側(cè)重:它具有singleTask 的全部特征之外端盆,獨(dú)占一個(gè)任務(wù)棧怀骤,并且系統(tǒng)的全局唯一性!爱谁!
如果多個(gè)應(yīng)用啟動(dòng)同一個(gè)activty頁(yè)面晒喷,則會(huì)在不用應(yīng)用之中可以復(fù)用這個(gè)頁(yè)面。執(zhí)行onNewIntent方法
點(diǎn)擊第四個(gè)按鈕
進(jìn)入SingleInstance頁(yè)面:
再點(diǎn)擊啟動(dòng)OtherActivity
點(diǎn)擊啟動(dòng)SingleInstance頁(yè)面
日志:
日志發(fā)現(xiàn)访敌,它啟動(dòng)的時(shí)候凉敲,taskID跟MainActivity的不一樣,并且在SingleInstance頁(yè)面啟動(dòng)的OtherActivity的TaskID 也是不與SingleInstanceActivity的相同寺旺!
說(shuō)明SingleInstance是獨(dú)占任務(wù)棧的爷抓!
只要實(shí)例存在,就會(huì)復(fù)用阻塑,同時(shí)它具有SingleTask的全部特性蓝撇!!
至此:Activity的四種啟動(dòng)模式已經(jīng)講完。
開(kāi)源代碼鏈接 : https://github.com/IDBAI/ActLuanchModelTest