好久以前就知道android
的Activity
有不同的啟動方式,但開始始終沒有弄明白,現(xiàn)在終于梳理清了。
任務棧
Activity
一共有四種不同的啟動模式,分別是standard
余佃、singleTop
、singleTask
跨算、singleInstance
爆土,不同的啟動模式,就讓activity存在于內(nèi)存中不同的任務棧和棧里的位置诸蚕。這里我們提到了一個任務棧步势,其實就是一個后進先出
的容器,里面存放著Activity
背犯。
在這樣一個任務棧里面坏瘩,相當于先讓Activity_A
進棧(直接啟動Activity_A
),然后再讓Activity_B
進棧(從Activity_A
以某種模式啟動Activity_B
,具體什么方式后面就講),剩下的Activity_C
漠魏、Activity_D
也是按照這種方式進棧倔矾。然后就是出棧了,首先我們明白現(xiàn)在的任務棧中有4個Activity
柱锹,接著當我們按手機的back
鍵的時候哪自,就會按照D,C,B,A出棧,這也就是所說的先進后出
禁熏。當然办铡,屏幕顯示的就是棧頂?shù)脑亓恕?/p>
四種啟動模式
一.standard (標準模式)
standard
字面意思就是標準叶骨,沒錯漫试,就是標準模式蛾号。當Activity
以標準模式啟動的時候锌蓄,就會把該Activity
給放入棧頂升筏。沒錯,我們上面的例子就可以用standard
模式啟動瘸爽。
二.singleTop(棧頂復用模式)
singleTop
模式就是講您访,當我們以singleTop
啟動Activity的時候,如果這時候的棧頂元素也是我們的需要啟動的Activity
剪决,那么這個Activity
就不會再次被創(chuàng)建灵汪,而是回調(diào)onNewIntent
方法檀训。
其實這個還是很好理解的,也就和字面意思一樣享言。好峻凫,我們看上面的任務棧,左邊就是我們開始的樣子(DCBA)览露,然后我們再以singleTop
模式去啟動D,然后荧琼,發(fā)現(xiàn)任務棧中還是(DCBA)。這就是棧頂復用模式差牛。
二.singleTask(棧內(nèi)復用模式)
singleTask
是我覺得這幾種模式中最難理解的命锄,但是慢慢理一下,發(fā)現(xiàn)還是挺簡單的偏化。
以singleTask
模式啟動的Activity
首先就會尋找自己需要的任務棧脐恩,如果沒有,就會創(chuàng)建一個侦讨,然后把自己給放進棧里面驶冒。要是有發(fā)現(xiàn)自己需要的任務棧,就會看里面有沒有這個Activity
的實例搭伤,沒有的話就在棧頂加入新創(chuàng)的實例只怎,要是有的話就會彈出該實例上面的所有元素,從而把所需求的實例給推到棧頂怜俐。
這樣一說身堡,肯定都還是模模糊糊的,不用怕拍鲤,我們慢慢理贴谎。首先,這里我們提出了一個新的術語季稳,"Activity
需要的任務棧"擅这。這里我們需要明白,當我們沒有為Activity
給指定任務棧的話,那它默認的就是我們項目的包名景鼠。當然仲翎,我們可以為其指定一個任務棧。
<activity
android:name=".Activity_C"
android:label="@string/title_activity_activity__c"
android:taskAffinity="com.mathias.www"
android:theme="@style/AppTheme.NoActionBar" />
在Activity
標簽中铛漓,通過taskAffinity
(任務相關性)給指定的字符串(字符串中必須包含分割符” . “),這樣當我們以singleTask
啟動該Activity
的時候溯香,就會新建一個任務棧。但是一般來說我們的Activity
都是以默認的taskAffinity
啟動的浓恶。
相同的任務棧
就如上圖一樣玫坛,起初我們的任務棧中有DCBA
四個元素,接著包晰,我們以singleTask
模式啟動B
,那么B
就不會被重新創(chuàng)建湿镀,而是回調(diào)onNewIntent
方法炕吸,并且,它還會清掉它上面的元素DC
(clearTop效果)勉痴,這時候你按back
鍵的話就是返回到A
赫模。
不同的任務棧
圖中,我們起初的默認任務棧中有BA
兩個元素蒸矛,然后我們以singleTask
(不同的任務棧嘴瓤,即改變了taskAffinity
)啟動C
,那么C
就會被放到另一個任務棧中,同時莉钙,由于C
在前臺廓脆,所以C
屬于的任務棧也會被變成我們的前臺任務棧。
當然磁玉,有些人可能會說停忿,C
不在默認的任務棧中了,但是我們按back
鍵還是會回到B
呀蚊伞?對席赂,當然會回到B
。當前臺任務棧返回的是時候棧里已經(jīng)沒有了元素了时迫,所以就會返回到后臺任務棧了颅停。
或許你又會說,那這樣啟動Activity
有什么作用嗎掠拳?好吧癞揉,當我們在同一個應用以不同的任務棧啟動的時候,好像這個作用并不大(怪我自己還沒找到)溺欧,但是在一個應用代開另一個應用的時候就起作用了喊熟,當一個應用A打開了另一個應用B的Acctvity
后,再返回Home
,打開應用B,就發(fā)現(xiàn)B沒有在主界面姐刁,而是開始A打開的界面芥牌,當然這里還需要一個Activity
的屬性支持 android:allowTaskReparenting="true"
。
singleInstance(單實例模式)
所謂的singleInstance
模式聂使,首先壁拉,它具備上一個singleTask
的所有屬性,其次柏靶,它只能獨自的存在于一個單獨的任務棧弃理。簡單點就是說,當以singleInstance
啟動Activity
的時候,會為它創(chuàng)建一個新的任務棧宿礁,而且這個任務棧只會有它一個Activity
案铺,后續(xù)的請求也都不會再重新創(chuàng)建它了蔬芥,所以叫做單例
梆靖。
好吧控汉,我們還是簡單的分析一下(搞什么,圖和上面的一樣):假設我們當前任務棧中有BA
,接著我們以singleInstance
模式啟動C
返吻,那么C
就會在一個獨立的任務棧中了姑子,然后我們的請求可能會讓前臺任務棧又變成了默認的(BA
),這時候测僵,我們再啟動C
,就不會創(chuàng)建C
,而是直接把C
這個任務棧變成前臺任務棧街佑,顯示C
。
也許你看過上面的分析又會有疑問了:明明上面的操作用singleTask
就能完成,為什么還要用singleInstance
?
的確捍靠,上面的操作換成singleTask
也是可以完成的沐旨,但是看我們這圖里面的情況,BA
為默認的任務棧榨婆,C
為新建的磁携。這時候,我們啟動一個和C
任務棧相同的D
,那么這里就會變成DC
良风。
然后谊迄,我們一系列的操作 ,又讓前臺任務棧變成了
BA
,我們這時候啟動C
,那么由于開始說的clearTop
屬性就會把D
給清理出去了烟央。再創(chuàng)建D
的時候就會重建了统诺,然而,如果使用的是singleInsatnce
的話就不會出現(xiàn)這種情況了疑俭,因為singleInstance
中只能有一個Activity
粮呢。
設置啟動模式
說了這么多,才發(fā)現(xiàn)還沒有講如何設置......
好吧钞艇,設置Activity
啟動模式有兩種方法鬼贱,一種就是在AndroidManifest.xml
中Activity
的launchMode
:
<activity
android:name=".Activity_B"
android:launchMode="singleInstance"
android:allowTaskReparenting="true"
android:label="@string/title_activity_activity__b"
android:theme="@style/AppTheme.NoActionBar" />
另一種就是在代碼中設置標志符了:
Intent intent = new Intent(Activity_A.this,Activity_B.class);
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(intent);
這兩種方式都可以設置,但是代碼設置的優(yōu)先級肯定是比在xml中高的(在代碼中先解析xml香璃,再設置的)这难。
最后
還有,這些是我參考《Android開發(fā)藝術探索》的葡秒,對姻乓,就是任大大的。