一、TaskAffinity
TaskAffinity翻譯過來就是“任務(wù)相關(guān)性”,它表示了一個Activity所需要的任務(wù)棧的名字。
在平時的開發(fā)中,我們一般很少使用到TaskAffinity這個屬性,也沒有聽說過Activity需要什么任務(wù)棧之類的。其實,在默認情況下,如果不指定TaskAffinity屬性,Activity所需任務(wù)棧的名字就是應(yīng)用的名字。
1、默認的任務(wù)棧
我們在一個應(yīng)用中啟動三個Activity,然后在Terminal中執(zhí)行adb shell dumpsys activity命令,結(jié)果如下:
Running activities (most recent first):
TaskRecord{853dee #503 A=com.hwldzh.myapplication U=0 StackId=1 sz=3}
Run #4: ActivityRecord{c1a608e u0 com.hwldzh.myapplication/.ThirdActivity t503}
Run #3: ActivityRecord{7289178 u0 com.hwldzh.myapplication/.SecondActivity t503}
Run #2: ActivityRecord{8539f65 u0 com.hwldzh.myapplication/.MainActivity t503}
可以看到,啟動的三個Activity都位于“com.hwldzh.application”這個任務(wù)棧中,而這個名字就是我們這個應(yīng)用的包名。
2、TaskAffinity初登場
接下來,我們給ThirdActivity加上TaskAffinity的屬性,即在Manifest中的聲明如下:
<activity
android:name=".ThirdActivity"
android:taskAffinity="com.hwldzh.ThirdActivity"/>
我們繼續(xù)執(zhí)行在Terminal中執(zhí)行adb shell dumpsys activity命令,看ThirdActivity是否處于“com.hwldzh.ThirdActivity”的任務(wù)棧中:
Running activities (most recent first):
TaskRecord{853dee #503 A=com.hwldzh.myapplication U=0 StackId=1 sz=3}
Run #4: ActivityRecord{c1a608e u0 com.hwldzh.myapplication/.ThirdActivity t503}
Run #3: ActivityRecord{7289178 u0 com.hwldzh.myapplication/.SecondActivity t503}
Run #2: ActivityRecord{8539f65 u0 com.hwldzh.myapplication/.MainActivity t503}
可以看到ThirdActivity依然運行在以包名為名字的任務(wù)棧中。這說明了在啟動模式為Standard下,單獨使用TaskAffinity屬性是無效的。
3、TaskAffinity和SingleTask配合
我們在ThirdActivity的Manifest聲明中加上SingleTask啟動模式:
<activity
android:name=".ThirdActivity"
android:launchMode="singleTask"
android:taskAffinity="com.hwldzh.ThirdActivity"/>
然后執(zhí)行adb shell dumpsys activity命令,得到如下結(jié)果:
Running activities (most recent first):
TaskRecord{5da8e4c #25630 A=com.hwldzh.ThirdActivity U=0 StackId=1 sz=1}
Run #7: ActivityRecord{1111a92 u0 com.hwldzh.myapplication/.ThirdActivity t25630}
TaskRecord{b00bc91 #25629 A=com.hwldzh.myapplication U=0 StackId=1 sz=2}
Run #6: ActivityRecord{93040cf u0 com.hwldzh.myapplication/.SecondActivity t25629}
Run #5: ActivityRecord{464be1f u0 com.hwldzh.myapplication/.MainActivity t25629}
在將ThirdActivity的啟動模式改為SingleTask之后,可以看到ThirdActivity啟動的時候創(chuàng)建了一個新的任務(wù)棧,并且該任務(wù)棧的名字為TaskAffinity屬性設(shè)置的“com.hwldzh.ThirdActivity”。
所以,當(dāng)TaskAffinity和SingleTask啟動模式配對使用時,它是具有該模式的Activity的目前任務(wù)棧的名字,待啟動的Activity會運行在名字和TaskAffinity相同的任務(wù)棧中。
二、allowTaskReparenting
allowTaskReparenting屬性的作用是Activity的遷移。當(dāng)allowTaskReparenting屬性和TaskAffinity配合使用時,Activity可以從一個任務(wù)棧遷移到另一個任務(wù)棧。
遷移的規(guī)則是:從一個與該Activity TaskAffinity屬性不同的任務(wù)棧中遷移到與它TaskAffinity相同的任務(wù)棧中。
舉個例子:當(dāng)一個應(yīng)用A啟動了應(yīng)用B的某個Activity后,如果這個Activity的allowTaskReparenting屬性設(shè)置為true,那么當(dāng)應(yīng)用B被啟動,此Activity會直接從應(yīng)用A的任務(wù)棧轉(zhuǎn)移到應(yīng)用B的任務(wù)棧中。
具體點來說,現(xiàn)在有兩個應(yīng)用A和B,A啟動了B的一個Activity C,然后按Home鍵回到桌面,然后再單擊B的桌面圖標(biāo),這個時候不是啟動了B的主Activity,而是重新顯示了已經(jīng)被應(yīng)用A啟動的Activity C。我們也可以理解為,C從A的任務(wù)棧轉(zhuǎn)移到了B的任務(wù)棧中。
可以這么理解,由于A啟動了C,這個時候C只能運行在A的任務(wù)棧中,但是C屬于B應(yīng)用,正常情況下,它的TaskAffinity值肯定不可能和A的任務(wù)棧相同,所以當(dāng)B啟動后,B會創(chuàng)建自己的任務(wù)棧,這個時候系統(tǒng)發(fā)現(xiàn)C原本想要的任務(wù)棧已經(jīng)創(chuàng)建了,所以就把C從A的任務(wù)棧中轉(zhuǎn)移過來了。
參考書目
1、《Android開發(fā)藝術(shù)探索》