談起Activity的啟動(dòng)模式必不可少的要是launchMode剩膘、Flags、taskAffinity這三塊知識(shí)點(diǎn)酵幕,上一篇文章 深入理解Activity啟動(dòng)模式之launchMode 看過(guò)的同學(xué)都知道該文章對(duì)launchMode做了非常詳細(xì)的講解记餐,所以本片文章承接上一篇文章對(duì)剩余的Flags剑勾、taskAffinity這兩塊做講述,希望看完此片文章的同學(xué)們此后遇到Activity的啟動(dòng)模式相關(guān)問(wèn)題或使用場(chǎng)景再也不用查資料_瞬铸。
(PS:本篇文章的實(shí)驗(yàn)數(shù)據(jù)都基于Android7.0)
Activity啟動(dòng)模式之Flags
先來(lái)看看常用Flags:
- Intent.FLAG_ACTIVITY_SINGLE_TOP
??該標(biāo)志位表示使用singleTop模式來(lái)啟動(dòng)一個(gè)Activity而钞,與在清單文件指定android:launchMode="singleTop"效果相同。
- Intent.FLAG_ACTIVITY_CLEAR_TOP
??該標(biāo)志位表示使用singleTask模式來(lái)啟動(dòng)一個(gè)Activity翎猛,與在清單文件指定android:launchMode="singleTask"效果相同胖翰。 - Intent.FLAG_ACTIVITY_NO_HISTORY
??使用該模式來(lái)啟動(dòng)Activity,當(dāng)該Activity啟動(dòng)其他Activity后切厘,該Activity就被銷(xiāo)毀了萨咳,不會(huì)保留在任務(wù)棧中。如A-B,B中以這種模式啟動(dòng)C迂卢,C再啟動(dòng)D某弦,則任務(wù)棧只有ABD桐汤。 - Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
??使用該標(biāo)識(shí)位啟動(dòng)的Activity不添加到最近應(yīng)用列表,也即我們從最近應(yīng)用里面查看不到我們啟動(dòng)的這個(gè)activity靶壮。與屬性android:excludeFromRecents="true"效果相同怔毛。 - Intent.FLAG_ACTIVITY_NEW_TASK
該標(biāo)志位表示使用一個(gè)新的Task來(lái)啟動(dòng)一個(gè)Activity,相當(dāng)于在清單文件中給Activity指定“singleTask”啟動(dòng)模式腾降。通常我們?cè)赟ervice啟動(dòng)Activity時(shí)拣度,由于Service中并沒(méi)有Activity任務(wù)棧,所以必須使用該Flag來(lái)創(chuàng)建一個(gè)新的Task螃壤。
使用也非常簡(jiǎn)單:
public static void startActivity(Context context) {
Intent intent = new Intent(context, HomeActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(new Intent(context, HomeActivity.class));
}
android:taskAffinity
我們重點(diǎn)來(lái)看看taskAffinity這個(gè)標(biāo)簽
android:taskAffinity 官網(wǎng)解釋
與 Activity 有著親和關(guān)系的任務(wù)抗果。從概念上講,具有相同親和關(guān)系的 Activity 歸屬同一任務(wù)(從用戶的角度來(lái)看奸晴,則是歸屬同一“應(yīng)用”)冤馏。 任務(wù)的親和關(guān)系由其根 Activity 的親和關(guān)系確定。
親和關(guān)系確定兩件事 - Activity 更改到的父項(xiàng)任務(wù)(請(qǐng)參閱 allowTaskReparenting 屬性)和通過(guò) FLAG_ACTIVITY_NEW_TASK 標(biāo)志啟動(dòng) Activity 時(shí)將用來(lái)容納它的任務(wù)寄啼。
默認(rèn)情況下逮光,應(yīng)用中的所有 Activity 都具有相同的親和關(guān)系。您可以設(shè)置該屬性來(lái)以不同方式組合它們墩划,甚至可以將在不同應(yīng)用中定義的 Activity 置于同一任務(wù)內(nèi)涕刚。 要指定 Activity 與任何任務(wù)均無(wú)親和關(guān)系,請(qǐng)將其設(shè)置為空字符串乙帮。
如果未設(shè)置該屬性杜漠,則 Activity 繼承為應(yīng)用設(shè)置的親和關(guān)系(請(qǐng)參閱 <application> 元素的 taskAffinity 屬性)。 應(yīng)用默認(rèn)親和關(guān)系的名稱(chēng)是 <manifest> 元素設(shè)置的軟件包名稱(chēng)察净。
我們來(lái)總結(jié)一下上邊文字包含的信息:
- TASK的taskAffinity是有它的根Activity的taskAffinity決定的驾茴;
- Activity的taskAffinity默認(rèn)值為所在應(yīng)用程序的包名;
- taskAffinity影響Activity的任務(wù)(TASK)從屬塞绿;
我們先來(lái)看看截取的一段堆棧信息:
Running activities (most recent first):
TaskRecord{f51ba40 #6608 A=com.tzx.launchmodel U=0 StackId=1 sz=2}
Run #3: ActivityRecord{6158b8a u0 com.tzx.launchmodel/.BActivity t6608}
TaskRecord{3e0d8d2 #6609 A=com.tzx.single U=0 StackId=1 sz=1}
Run #2: ActivityRecord{d387da3 u0 com.tzx.launchmodel/.CActivity t6609}
TaskRecord{f51ba40 #6608 A=com.tzx.launchmodel U=0 StackId=1 sz=2}
Run #1: ActivityRecord{a0bfd79 u0 com.tzx.launchmodel/.AActivity t6608}
該堆棧信息對(duì)應(yīng)的AndroidManifest.xml:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.tzx.launchmodel" >
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme" >
<activity android:name=".AActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".BActivity"/>
<activity android:name=".CActivity"
android:taskAffinity="com.tzx.single"
android:launchMode="singleInstance"/>
</application>
</manifest>
其中TaskRecord中的A的值就是taskAffinity沟涨。
- taskAffinity一班與singleTask、singleInstance和allowTaskReparenting標(biāo)簽搭配使用异吻。
這句話又怎么理解呢裹赴?
在解釋這句時(shí)我先想和大家先聊聊Android手機(jī)在使用過(guò)程中為了手機(jī)軟件運(yùn)行的更加流暢,我們一般都會(huì)清理后臺(tái)任務(wù)诀浪。這個(gè)任務(wù)列表是我們最能直觀的看到任務(wù)的存在痕跡棋返。在這里我們會(huì)看到很多情況:一個(gè)應(yīng)用程序的所有Activity一個(gè)任務(wù),多個(gè)應(yīng)用程序的不同Activity一個(gè)任務(wù)雷猪,一個(gè)應(yīng)用程序不同Activity在不同任務(wù)中睛竣。此時(shí)是不是感覺(jué)很懵逼,沒(méi)關(guān)系接下來(lái)我會(huì)講述為什么會(huì)這樣:
taskAffinity.jpg
- 一個(gè)應(yīng)用程序的所有Activity一個(gè)任務(wù):一班情況下都這樣(不設(shè)置taskAffinity)求摇。
- 多個(gè)應(yīng)用程序的不同Activity一個(gè)任務(wù):一個(gè)應(yīng)用程序啟動(dòng)另外一個(gè)應(yīng)用程序的Activity并且這里只能是standard或者singleTop模式射沟。因?yàn)槲覀兊贸龅牡谌齻€(gè)結(jié)論taskAffinity只會(huì)對(duì)singleTask殊者、singleInstance有影響,所以在啟動(dòng)standard或者singleTop模式的Activity時(shí)不會(huì)對(duì)比taskAffinity验夯,會(huì)直接在啟動(dòng)它的TASK中啟動(dòng)猖吴。而啟動(dòng)singleTask、singleInstance模式的Activity只能在對(duì)應(yīng)的taskAffinity的TASK中挥转。
- 一個(gè)應(yīng)用程序不同Activity在不同任務(wù)中:當(dāng)在應(yīng)用程序中我們啟動(dòng)singleTask模式的Activity時(shí)會(huì)尋找與該Activity的taskAffinity相同的TASK當(dāng)中啟動(dòng)海蔽,如果沒(méi)有則會(huì)新建一個(gè)TASK并且這個(gè)TASK在任務(wù)列表里展示。這時(shí)可能比較細(xì)心的同學(xué)會(huì)問(wèn)singleInstance模式的Activity呢绑谣?它每次都會(huì)啟動(dòng)一個(gè)TASK党窜,那么任務(wù)列表里面會(huì)展示這個(gè)TASK么?如果任務(wù)列表中不存在TASK與該singleInstance模式的Activity的taskAffinity
相同借宵,那么該TASK出現(xiàn)中在任務(wù)列表幌衣。如果有那么不出現(xiàn)在任務(wù)列表。
android:allowTaskReparenting
android:allowTaskReparenting這個(gè)標(biāo)簽我們單獨(dú)抽出來(lái)講一下壤玫,為什么呢泼掠?因?yàn)槲腋杏X(jué)android:allowTaskReparenting和taskAffinity沒(méi)啥關(guān)系,至與launchMode有關(guān)?严浮!挡逼!
android:allowTaskReparenting 官網(wǎng)解釋
當(dāng)啟動(dòng) Activity 的任務(wù)接下來(lái)轉(zhuǎn)至前臺(tái)時(shí)括改,Activity 是否能從該任務(wù)轉(zhuǎn)移至與其有親和關(guān)系的任務(wù) —“true”表示它可以轉(zhuǎn)移,“false”表示它仍須留在啟動(dòng)它的任務(wù)處家坎。
如果未設(shè)置該屬性嘱能,則對(duì) Activity 應(yīng)用由 <application> 元素的相應(yīng) allowTaskReparenting 屬性設(shè)置的值。 默認(rèn)值為“false”虱疏。
正常情況下惹骂,當(dāng) Activity 啟動(dòng)時(shí),會(huì)與啟動(dòng)它的任務(wù)關(guān)聯(lián)做瞪,并在其整個(gè)生命周期中一直留在該任務(wù)處对粪。您可以利用該屬性強(qiáng)制 Activity 在其當(dāng)前任務(wù)不再顯示時(shí)將其父項(xiàng)更改為與其有親和關(guān)系的任務(wù)。該屬性通常用于使應(yīng)用的 Activity 轉(zhuǎn)移至與該應(yīng)用關(guān)聯(lián)的主任務(wù)装蓬。
例如著拭,如果電子郵件包含網(wǎng)頁(yè)鏈接,則點(diǎn)擊鏈接會(huì)調(diào)出可顯示網(wǎng)頁(yè)的 Activity牍帚。 該 Activity 由瀏覽器應(yīng)用定義儡遮,但作為電子郵件任務(wù)的一部分啟動(dòng)。 如果將其父項(xiàng)更改為瀏覽器任務(wù)暗赶,它會(huì)在瀏覽器下一次轉(zhuǎn)至前臺(tái)時(shí)顯示鄙币,當(dāng)電子郵件任務(wù)再次轉(zhuǎn)至前臺(tái)時(shí)則會(huì)消失肃叶。
Activity 的親和關(guān)系由 taskAffinity 屬性定義。 任務(wù)的親和關(guān)系通過(guò)讀取其根 Activity 的親和關(guān)系來(lái)確定十嘿。因此因惭,按照定義,根 Activity 始終位于具有相同親和關(guān)系的任務(wù)之中详幽。 由于具有“singleTask”或“singleInstance”啟動(dòng)模式的 Activity 只能位于任務(wù)的根筛欢,因此更改父項(xiàng)僅限于“standard”和“singleTop”模式。 (另請(qǐng)參閱 launchMode 屬性唇聘。)
上面文字?jǐn)⑹隹偨Y(jié)為一句話:android:allowTaskReparenting可以讓Activity在TASK中轉(zhuǎn)移版姑,但該Activity時(shí)能是“standard”和“singleTop”模式。
至于為什么在講taskAffinity的時(shí)候已經(jīng)介紹清楚了迟郎。實(shí)用場(chǎng)景官網(wǎng)的描述中也有剥险,大家可以參考使用。
文章到這里就全部講述完啦宪肖,若有其他需要交流的可以留言哦~表制!~!