Android TaskAffinity實踐詳解

再見理想2017發表於2017-06-05

介紹

其實一直以來都知道在AndroidManifest的Activity中可以配置TaskAffinity這個屬性,只知道這個東西和Activity的任務棧有關,今天花了點時間好好學習了一些這個東西。

launchMode(啟動模式)

Activity的任務棧是我們很熟悉的了,它是一種後進先出的結構。位於棧頂的Activity處於焦點狀態,當按下back按鈕的時候,棧內的Activity會一個一個的出棧,並且呼叫其onDestory()方法。如果棧內沒有Activity,那麼系統就會回收這個棧,每個APP預設只有一個棧,以APP的包名來命名.

1.
standard: 標準模式,每次啟動Activity都會建立一個新的Activity例項,並且將其壓入任務棧棧頂,而不管這個Activity是否已經存在。Activity的啟動三回撥(onCreate()->onStart()->onResume())都會執行。

2.
singleTop: 棧頂複用模式.這種模式下,如果新Activity已經位於任務棧的棧頂,那麼此Activity不會被重新建立,所以它的啟動三回撥就不會執行,同時Activity的onNewIntent()方法會被回撥.如果Activity已經存在但是不在棧頂,那麼作用與standard模式一樣.

3.
singleTask: 棧內複用模式.建立這樣的Activity的時候,系統會先確認它所需任務棧已經建立,否則先建立任務棧.然後放入Activity,如果棧中已經有一個Activity例項,那麼這個Activity就會被調到棧頂,onNewIntent(),並且singleTask會清理在當前Activity上面的所有Activity.(clear top)

4.
singleInstance: 加強版的singleTask模式,這種模式的Activity只能單獨位於一個任務棧內,由於棧內複用的特性,後續請求均不會建立新的Activity,除非這個獨特的任務棧被系統銷燬了

TaskAffinity

好了,現在要開始介紹TaskAffinity了,如果單獨設定TaskAffinity屬性的話是沒有任何效果的,只有Activity的launchMode設定成singTask的時候才會生效的。那麼現在我們就來驗證一下:

這裡需要注意的是:
1.TaskAffinity的值應該是xxx.xxx.xxx類似包名的,如果沒有包括.的話是安裝不了的;   
2.如果不指定TaskAffinity的話,預設的值是包名。複製程式碼
案例1

Android TaskAffinity實踐詳解

Android TaskAffinity實踐詳解

這裡的MainActivity中的程式碼很簡單,就是把當前的類名和TaskId列印出來,SecondActivity和ThirdActivity也是一樣的。

輸出:
cn.xdeveloper.activitytest.MainActivity
698

cn.xdeveloper.activitytest.SecondActivity
698

cn.xdeveloper.activitytest.ThirdActivity
698

這裡可以看到這三個Activity的TaskId都相同,可見TaskAffinity屬性並沒有起作用。

案例2

Android TaskAffinity實踐詳解

修改SencondActivity的launchMode=singleTask。

輸出:

cn.xdeveloper.activitytest.MainActivity
699

cn.xdeveloper.activitytest.SecondActivity
700

cn.xdeveloper.activitytest.ThirdActivity
700

這裡可以看到SecondActivity的TaskId改變了,啟動Activity的時候會根據taskAffinity查詢是否有存在的任務棧,沒有的話就建立一個新的任務棧。同時在啟動ThirdActivity,也會加入到當前的任務棧中。

案例3

Android TaskAffinity實踐詳解

修改SencondActivity的launchMode=singleInstance,其他不變。

輸出:

cn.xdeveloper.activitytest.MainActivity
703

cn.xdeveloper.activitytest.SecondActivity
704

cn.xdeveloper.activitytest.ThirdActivity
703

可以看到SecondActivity是建立在新的棧裡,而ThirdActivity卻還是建立在原來的棧裡面,這是因為singleInstance的特性造成的,它會建立一個新的棧並且裡邊就只有一個Activity例項,所以和singTask不同,之後啟動的ThirdActivity不會進入到該棧中。

其實這裡SecondActivity中設定的taskAffinity是沒意義的,就算不設定結果也是一樣的,因為singleInstance會建立一個新的棧並只能儲存唯一的Activity,所以其他的Activity就算設定了一樣的taskAffinity也不起作用了。

這裡講一下啟動過程:
MainActivity(703棧進入前臺) --> SecondActivity(704棧進入前臺,703棧進入後臺) --> ThirdActivity(703棧進入前臺,704棧進入後臺)

最終棧裡的情況是:
前臺:703棧(ThirdActivity、MainActivity)
後臺:702棧(SecondActivity)

所以這個時候依次點選返回鍵退回的話:
ThirdActivity --> MainActivity --> SecondActivity

總結

到這裡TaskAffinity的作用已經很明瞭了,通過這個屬性可以把不同的Activity分在不同的任務棧中,這裡總結一下重點:

1.TaskAffinity屬性只有在launchMode=singleTask的時候才有作用;(案例1、案例2)
2.正常情況下啟動的Activity會預設加到當前的前臺棧中;(案例2)

相關文章