taskAffinity 屬性詳解

  這篇文章用來(lái)記錄一下自己對(duì) taskaffinity 屬性的理解鼠哥,以幫助和我有相同困惑的同學(xué)侧但。不對(duì)之處還請(qǐng)各位看客指出,我會(huì)及時(shí)更正库北。

一尊沸、本文目的

本篇文章的目的是為了 搞清楚,哪些情況下開啟一個(gè) Activity 會(huì)在新的 task 運(yùn)行贤惯,哪些情況下會(huì)繼續(xù)在原來(lái)的task 運(yùn)行洼专。

二、相關(guān)基礎(chǔ)知識(shí)

知識(shí)點(diǎn) 1

每個(gè) Activity 運(yùn)行時(shí)都有一個(gè)其歸屬的 task棧孵构,我們可以用 activity.getTaskId() 的方法得到當(dāng)前 activity 的taskId屁商。如果兩個(gè) activity 的 taskId 不同,則他們肯定不會(huì)屬于同一個(gè) task颈墅。

為了方便蜡镶,我們?cè)?Application 中注冊(cè)生命周期回調(diào),類似這樣恤筛,我們打印出當(dāng)前 activity 和其歸屬的 taskid官还。

public class MyApplication extends Application {
    private static final String  TAG_APP = MyApplication.class.getSimpleName();
    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG_APP,"MyApplication#onCreate"+Thread.currentThread().getName();
        registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
            //已過(guò)濾無(wú)用代碼,只在onresume 讀取相關(guān)數(shù)據(jù)
            @Override
            public void onActivityResumed(Activity activity) {
                Log.d(TAG_APP,"onActivityResumed+"+activity.getClass().getSimpleName()+"####taskid = "+activity.getTaskId());
            }
        });

    }
}

知識(shí)點(diǎn) 2

taskAffinity 的使用方式如下毒坛,


image.png

如上圖所示望伦,taskaffinity 可以單獨(dú)對(duì)一個(gè) activity 使用林说,代表該 activity 所想歸屬的 task;
也能對(duì)application 使用屯伞,代表該 application 內(nèi)聲明的所有 activity 都?xì)w屬于這個(gè)task腿箩。

如果 activity 組件沒有聲明 taskAffinity 的話,該 activity 的 taskAffinity 屬性也是有默認(rèn)值的劣摇。如果 application 指定了 taskAffinity 值珠移,默認(rèn)值就是 application 指定的 taskAffinity 值;如果 application 未指定的話末融,默認(rèn)值就是 manifest 中聲明的包名(package 對(duì)應(yīng)的字符串)钧惧。

知識(shí)點(diǎn) 3

Android 手機(jī)的任務(wù)列表就是根據(jù)不同 task 彈出的,我們可以根據(jù)任務(wù)管理器有幾個(gè) item 圖標(biāo)勾习,來(lái)知道我們開啟了幾個(gè) task浓瞪。

知識(shí)點(diǎn) 4

是不是我指定了一個(gè) Activity 的 taskAffinity 值(跟包名不同),運(yùn)行該 Activity 時(shí)语卤,是否就會(huì)新開這個(gè) task棧呢?

答案是否定的酪刀,一個(gè) Activity 運(yùn)行時(shí)所歸屬的task粹舵,默認(rèn)是啟動(dòng)它 的那個(gè)Activity 所在的 task(下文將會(huì)驗(yàn)證)。

知識(shí)點(diǎn) 5

taskAffinity 單獨(dú)使用并不會(huì)生效骂倘。
要想其生效眼滤,需要配合其他屬性使用,或者配合 Intent.FLAG_ACTIVITY_NEW_TASK历涝,或者配合
allowTaskReparenting 诅需。使用時(shí)用其中的一個(gè)就行,下面將詳細(xì)介紹這兩個(gè)屬性荧库。

三堰塌、Intent.FLAG_ACTIVITY_NEW_TASK

Intent.FLAG_ACTIVITY_NEW_TASK 使用方式如下,

Intent intent = new Intent(this,IntentTimeActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);

3.1 FLAG_ACTIVITY_NEW_TASK 解析規(guī)則

首先說(shuō)下這個(gè)規(guī)則是根據(jù)測(cè)試結(jié)果反推出來(lái)的分衫,不對(duì)之處還還請(qǐng)指出(捂臉场刑。。蚪战。)

==當(dāng) AMS 發(fā)現(xiàn)啟動(dòng)了一個(gè)帶有 FLAG_ACTIVITY_NEW_TASK 標(biāo)簽的 Activity 時(shí)牵现,會(huì)先去尋找當(dāng)前是否存在這個(gè) Activity 的 task 值(這個(gè)值具體是什么可看 知識(shí)點(diǎn)2),如果不存在的話邀桑,就會(huì)創(chuàng)建該task瞎疼,如果存在就省去了創(chuàng)建 task 這個(gè)步驟。然后在把要啟動(dòng)的 Activity 添加到 task 中壁畸。

3.2 測(cè)試case和結(jié)果

下面開始我們的測(cè)試贼急,測(cè)試結(jié)果為過(guò)濾后的log日志茅茂,并給出相應(yīng)分析。


我們假定都是 Activity A 跳轉(zhuǎn)到 Activity B 中竿裂,A沒有指定 taskAffinity 屬性,B 的launchMode 為standard玉吁。

case1: A、B 屬同一App, intent 未指定 FLAG_ACTIVITY_NEW_TASK腻异,B 未指定 taskAffinity 屬性
D/MyApplication: onActivityResumed+MainActivity####taskid = 61 
D/MyApplication: onActivityResumed+KeyboardActivity####taskid = 61

可以驗(yàn)證:一個(gè)Activity 歸屬的task 是由 啟動(dòng)它的 Activity 所決定的进副。

case2: A、B 屬同一App,intent 未指定 FLAG_ACTIVITY_NEW_TASK悔常,B 指定 taskAffinity 屬性影斑,但與包名相同
D/MyApplication: onActivityResumed+MainActivity####taskid = 62 
D/MyApplication: onActivityResumed+KeyboardActivity####taskid = 62

可以驗(yàn)證,一個(gè) Activity 的默認(rèn) task 值就是 manifest 定義的包名机打。

case3: A矫户、B 屬同一App,intent 未指定 FLAG_ACTIVITY_NEW_TASK,B 指定 taskAffinity 屬性残邀,但與包名不同
D/MyApplication: onActivityResumed+MainActivity####taskid = 63
D/MyApplication: onActivityResumed+KeyboardActivity####taskid = 63

可以驗(yàn)證:不指定 FLAG_ACTIVITY_NEW_TASK的話皆辽, 即使 taskAffinity 不同,一個(gè)Activity 歸屬的task 仍然是由 啟動(dòng)它的 Activity 所決定的芥挣。

case4: A驱闷、B 屬同一App,intent 指定 FLAG_ACTIVITY_NEW_TASK,B 未指定 taskAffinity 屬性
D/MyApplication: onActivityResumed+MainActivity####taskid = 64
D/MyApplication: onActivityResumed+KeyboardActivity####taskid = 64

可以驗(yàn)證:即使 使用了 FLAG_ACTIVITY_NEW_TASK空免,但由于兩者的 taskAffinity 相同空另,所以仍然不會(huì)開啟一個(gè)新的task。

case5: A蹋砚、B 屬同一App,intent 指定 FLAG_ACTIVITY_NEW_TASK扼菠,B 指定 taskAffinity 屬性,且和包名不同
D/MyApplication: onActivityResumed+MainActivity####taskid = 65
D/MyApplication: onActivityResumed+KeyboardActivity####taskid = 66

可以驗(yàn)證:開啟一個(gè)新task 的條件是 FLAG_ACTIVITY_NEW_TASK 和 taskAffinity 不同 缺一不可坝咐。


case6: A循榆、B 屬同一App,intent 未指定 FLAG_ACTIVITY_NEW_TASK,B 未指定 taskAffinity 屬性墨坚,B啟動(dòng)模式為 singletask or singletop
D/MyApplication: onActivityResumed+MainActivity####taskid = 67
D/MyApplication: onActivityResumed+KeyboardActivity####taskid = 67

可以得出:未指定 FLAG_ACTIVITY_NEW_TASK 和 新的 taskAffinity 時(shí)冯痢,這兩種啟動(dòng)模式對(duì)task 沒有影響

case7: A、B 屬同一App,intent 未指定 FLAG_ACTIVITY_NEW_TASK框杜,B 未指定 taskAffinity 屬性浦楣,B啟動(dòng)模式為 singleinstance
D/MyApplication: onActivityResumed+MainActivity####taskid = 70
D/MyApplication: onActivityResumed+KeyboardActivity####taskid = 71

可以得出:
singleinstance 啟動(dòng)模式本身就是會(huì)開啟一個(gè)新的task 裝載 這個(gè)Activity,且task 中只有這一個(gè) Activity咪辱。
經(jīng)判斷得知振劳,AMS 是先對(duì) launchMode 做判斷 再處理 FLAG_ACTIVITY_NEW_TASK 的,如果是 singleinstance 油狂,則會(huì)直接開啟一個(gè)task历恐。


上面七個(gè) case 均是在同一個(gè)app 內(nèi)的寸癌,現(xiàn)在考慮跨進(jìn)程調(diào)用的情況,A在 app1弱贼,B在app2蒸苇,此時(shí) B 的默認(rèn) task 肯定是和 A 不同的
我們可以通過(guò)隱式啟動(dòng)的方式啟動(dòng)B吮旅,B 仍然是標(biāo)準(zhǔn)啟動(dòng)模式溪烤。
類似這樣

//App1中 在Activity A 中我們這樣定義跳轉(zhuǎn)方法
public void onClickApp2(View v){
        Intent intent = new Intent("xxx.lzq");//action 自己隨便定義就行,但要保證 跟 B 的 intent-filter 是相同的庇勃。
        intent.addCategory(Intent.CATEGORY_DEFAULT);
        startActivity(intent);
    }
    
//app2 中 manifest文件這樣定義
<activity android:name=".Main2Activity">
            <intent-filter>
                <action android:name="xxx.lzq"/>
                <category android:name="android.intent.category.DEFAULT"/>
            </intent-filter>
        </activity>

++下文 所有的 App1的log標(biāo)識(shí)為 MyApplication檬嘀,App2 的標(biāo)識(shí)為 MyApplication2。++

case 8: intent 未指定 FLAG_ACTIVITY_NEW_TASK
D/MyApplication: onActivityResumed+MainActivity####taskid = 74
D/MyApplication2: onActivityResumed+Main2Activity####taskid = 74

可以得出:case 8 與 case 3 的本質(zhì)是相同的责嚷,僅僅是 A 和 B 的taskA 屬性不同鸳兽,所以沒有開啟新的task。
我們還可以看出罕拂,task 是可以跨進(jìn)程的揍异,即一個(gè) task 中的 Activities 是可以運(yùn)行在不同的進(jìn)程中的。(關(guān)于 A 和 B 不在同一個(gè)進(jìn)程讀者可自行驗(yàn)證)

case 9: intent 指定 FLAG_ACTIVITY_NEW_TASK
D/MyApplication: onActivityResumed+MainActivity####taskid = 76
D/MyApplication2: onActivityResumed+Main2Activity####taskid = 77

可以得出:case 9 與 case 5 的本質(zhì)是相同的爆班。

至此衷掷,Intent 的 FLAG_ACTIVITY_NEW_TASK 屬性 應(yīng)該算是講解清楚了。

我們還可以得出一個(gè)有意思結(jié)論蛋济,那就是 AMS 分配的taskid 是線性遞增的棍鳖,每次開啟一個(gè)新的task 炮叶,taskid 永遠(yuǎn)都是 +1 的操作碗旅。

四、allowTaskReparenting 相關(guān)

測(cè)試該屬性的話镜悉,應(yīng)該先把 FLAG_ACTIVITY_NEW_TASK 屬性去掉祟辟。

allowTaskReparenting 這個(gè)屬性指的是一個(gè) Activity 運(yùn)行時(shí),可以重新選擇自己所屬的task侣肄【衫В基本是在跨app 間調(diào)用時(shí),我們?cè)谏厦娴腸ase 8 的基礎(chǔ)上稼锅,對(duì) Activity 做如下修改

// 將 allowTaskReparenting 設(shè)置為 true
<activity android:name=".Main2Activity"
            android:allowTaskReparenting="true"> 
            <intent-filter>
                <action android:name="xxx.lzq"/>
                <category android:name="android.intent.category.DEFAULT"/>
            </intent-filter>
        </activity>
case 10: taskReparenting 的時(shí)機(jī):

當(dāng) A 啟動(dòng) B 時(shí)吼具,這時(shí)雖然是在兩個(gè)進(jìn)程中的,但其歸屬的task 是同一個(gè)矩距,這時(shí)我們回到后臺(tái)拗盒,在桌面點(diǎn)擊 B 的應(yīng)用圖標(biāo),我們會(huì)發(fā)現(xiàn) log 日志如下:
其中 MyApplication 代表 app1锥债,MyApplication2代表 app2陡蝇。

D/MyApplication: onActivityResumed+MainActivity####taskid = 83
D/MyApplication2: onActivityResumed+Main2Activity####taskid = 83
D/MyApplication2: onActivityResumed+Main2Activity####taskid = 84
case 11: 假如 app2 之前啟動(dòng)過(guò)痊臭,即app2 所歸屬的task 已經(jīng)創(chuàng)建,這時(shí)我們?cè)偻耆貜?fù)以上步驟登夫,

log 日志如下:

D/MyApplication2: onActivityResumed+MainActivity####taskid = 86
D/MyApplication: onActivityResumed+MainActivity####taskid = 87
D/MyApplication2: onActivityResumed+Main2Activity####taskid = 87
D/MyApplication2: onActivityResumed+Main2Activity####taskid = 86

此 case 正好驗(yàn)證之前的解析規(guī)則广匙,若 Activity taskAffinity指定的task 已經(jīng)存在,是會(huì)復(fù)用之前的task恼策,而不會(huì)再重新創(chuàng)建一個(gè)新的task鸦致。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市戏蔑,隨后出現(xiàn)的幾起案子蹋凝,更是在濱河造成了極大的恐慌,老刑警劉巖总棵,帶你破解...
    沈念sama閱讀 212,454評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件鳍寂,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡情龄,警方通過(guò)查閱死者的電腦和手機(jī)迄汛,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)骤视,“玉大人鞍爱,你說(shuō)我怎么就攤上這事∽ㄐ铮” “怎么了睹逃?”我有些...
    開封第一講書人閱讀 157,921評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)祷肯。 經(jīng)常有香客問(wèn)我沉填,道長(zhǎng),這世上最難降的妖魔是什么佑笋? 我笑而不...
    開封第一講書人閱讀 56,648評(píng)論 1 284
  • 正文 為了忘掉前任翼闹,我火速辦了婚禮,結(jié)果婚禮上蒋纬,老公的妹妹穿的比我還像新娘猎荠。我一直安慰自己,他們只是感情好蜀备,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,770評(píng)論 6 386
  • 文/花漫 我一把揭開白布关摇。 她就那樣靜靜地躺著,像睡著了一般碾阁。 火紅的嫁衣襯著肌膚如雪输虱。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,950評(píng)論 1 291
  • 那天瓷蛙,我揣著相機(jī)與錄音悼瓮,去河邊找鬼戈毒。 笑死,一個(gè)胖子當(dāng)著我的面吹牛横堡,可吹牛的內(nèi)容都是我干的埋市。 我是一名探鬼主播,決...
    沈念sama閱讀 39,090評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼命贴,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼道宅!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起胸蛛,我...
    開封第一講書人閱讀 37,817評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤污茵,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后葬项,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體泞当,經(jīng)...
    沈念sama閱讀 44,275評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,592評(píng)論 2 327
  • 正文 我和宋清朗相戀三年民珍,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了襟士。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,724評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡嚷量,死狀恐怖陋桂,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情蝶溶,我是刑警寧澤嗜历,帶...
    沈念sama閱讀 34,409評(píng)論 4 333
  • 正文 年R本政府宣布,位于F島的核電站抖所,受9級(jí)特大地震影響梨州,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜部蛇,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,052評(píng)論 3 316
  • 文/蒙蒙 一摊唇、第九天 我趴在偏房一處隱蔽的房頂上張望咐蝇。 院中可真熱鬧涯鲁,春花似錦、人聲如沸有序。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,815評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)旭寿。三九已至警绩,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間盅称,已是汗流浹背肩祥。 一陣腳步聲響...
    開封第一講書人閱讀 32,043評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工后室, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人混狠。 一個(gè)月前我還...
    沈念sama閱讀 46,503評(píng)論 2 361
  • 正文 我出身青樓岸霹,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親将饺。 傳聞我的和親對(duì)象是個(gè)殘疾皇子贡避,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,627評(píng)論 2 350