原始文檔
docs/guide/components/tasks-and-back-stack.html
任務(wù)
- 任務(wù)(Task)是用戶執(zhí)行特定作業(yè)時(shí)的一系列交互活動(dòng)(Activity)务荆。這些活動(dòng)以打開的順序被存放在堆棧(返回棧)中贱勃。
-
當(dāng)Activity啟動(dòng)另外一個(gè)Activity,那么新的Activity被放置到棧的頂部并獲取焦點(diǎn)砌左。前一個(gè)Activity依然保留在棧中泽裳,但是出于停止?fàn)顟B(tài)例证。系統(tǒng)會(huì)保存處于停止?fàn)顟B(tài)的Activity的用戶界面。用戶摁返回鍵畦幢,當(dāng)前的Activity彈出銷毀入热,前一個(gè)Activity恢復(fù)執(zhí)行。整個(gè)啟動(dòng)-返回退出Activity的操作如下圖所示解总。
- 當(dāng)所有的Activity從棧中移除時(shí)贮匕,任務(wù)被銷毀。
- 返回棧中的所有Activity是不能重新被排序的花枫,這樣的話刻盐,如果允許一個(gè)Activity可以被多個(gè)其他Activity啟動(dòng)的話,那么每次會(huì)實(shí)例化一個(gè)Activity,并保存在棧中劳翰《匦浚可以通過啟動(dòng)方式來管理是否每次 都實(shí)例化一個(gè)全新的Activity。
- 當(dāng)用戶通過主頁按鈕離開當(dāng)前任務(wù)佳簸,當(dāng)前Activity停止乙墙,當(dāng)前任務(wù)進(jìn)入到后臺。系統(tǒng)會(huì)保持任務(wù)中的每個(gè)Activity的狀態(tài)生均。當(dāng)用戶通過點(diǎn)擊啟動(dòng)圖標(biāo)听想,任務(wù)恢復(fù)進(jìn)入前臺,任務(wù)頂端的Activity恢復(fù)狀態(tài)马胧。
Activity狀態(tài)保存
盡管系統(tǒng)會(huì)自動(dòng)保存后臺的Activity的狀態(tài)哗魂,但是如果在內(nèi)存緊張的情況下,系統(tǒng)會(huì)銷毀后臺Activity漓雅。這樣的話录别,一些Activity的重要的信息就會(huì)丟失朽色,在下次改Activity進(jìn)入前臺的時(shí)候,該意外銷毀的Activity會(huì)被重新創(chuàng)建组题,無法恢復(fù)葫男。為避免這種情況的發(fā)生,應(yīng)該主動(dòng)地調(diào)用onSaveInstanceState()來保存狀態(tài)崔列。
任務(wù)管理
正常的task是一個(gè)“先入后出”的堆棧梢褐,每次都實(shí)例一個(gè)Activity并且壓入堆棧。如果想打破這種常規(guī)赵讯,可以在AndroidManifest.xml的Activity申明啟動(dòng)模式盈咳、啟動(dòng)屬性等或者在startActivity()時(shí)指定標(biāo)志位。
清單文件中指定可使用屬性:
- taskAffinity (任務(wù)親戚關(guān)系)
- launchMode
- allowTaskReparenting
- clearTaskOnLaunch
- alwaysRetainTaskState
- finishOnTaskLaunch
Intent標(biāo)志:
- FLAG_Activity_NEW_TASK
- FLAG_Activity_CLEAR_TOP
- FLAG_Activity_SINGLE_TOP
在Intent和清單文件中啟動(dòng)方式發(fā)生沖突時(shí)边翼,以Intent中的啟動(dòng)方式為準(zhǔn)鱼响。
launchMode 啟動(dòng)模式
- "standard"
默認(rèn)啟動(dòng)方式,每次在任務(wù)種實(shí)例化一個(gè)Activity组底。一個(gè)Activity被實(shí)例化多次丈积,每個(gè)實(shí)例可能隸屬于不同的任務(wù),一個(gè)任務(wù)可能擁有多個(gè)該Activity的實(shí)例债鸡。 - "singleTop"
如果返回棧中存在Activity的實(shí)例江滨,并且該實(shí)例在任務(wù)的頂部,那么通過調(diào)用onNewIntent()進(jìn)入該Activity厌均,并不會(huì)重新實(shí)例化一個(gè)Activity唬滑。確保任務(wù)頂部的兩個(gè)Activity不重復(fù).
例如任務(wù)A-B-C-D,現(xiàn)在一個(gè)新的Intent啟動(dòng)D,如果D是默認(rèn)啟動(dòng)方式的話,會(huì)實(shí)例化一個(gè)先的Activity D棺弊,任務(wù)變成A-B-C-D-D;如果是singleTop的話间雀,只會(huì)調(diào)用D的onNewIntent()方法,任務(wù)依然是A-B-C-D镊屎。但是如果啟動(dòng)B的話惹挟,任務(wù)變成A-B-C-D-B,即使啟動(dòng)方式是singleTop。 - "singleTask"
所有的任務(wù)(返回棧)中僅能存在一個(gè)實(shí)例缝驳。如果所有的任務(wù)中不存在該Activity的實(shí)例连锯,那么實(shí)例化一個(gè)該Activity。如果存在的話用狱,那么進(jìn)入該Activity的onNewIntent()的方法运怖。
對于這種啟動(dòng)方式的Activity,對于返回的處理是比較特殊的。如果從一個(gè)新的任務(wù)中啟動(dòng)一個(gè)其他任務(wù)已存在的Activity夏伊,那么相當(dāng)于比之前任務(wù)的返回棧堆疊到到當(dāng)前堆棧上摇展。如下圖所示.

在上圖中Y是singleTask啟動(dòng)方式,Activity2啟動(dòng)Y后溺忧,摁返回咏连,不會(huì)立即返回到Activity2盯孙,而是按照Y所在的堆棧進(jìn)行返回。如果后臺任務(wù)順序?yàn)閄-Y-W,那么啟動(dòng)Y的時(shí)候祟滴,會(huì)先調(diào)用W.onDestory(),銷毀W,彈出Y振惰。
- "singleInstance"
這種方式是所有任務(wù)中只有一個(gè)Activity實(shí)例,這點(diǎn)跟singleTask是一樣的垄懂。所不同的是骑晶,該Activity獨(dú)占一個(gè)任務(wù),該任務(wù)不含其他的Activity草慧。
使用Intent標(biāo)志
可以在調(diào)用startActivity()時(shí)指定標(biāo)志位來指定Activity的啟動(dòng)方式桶蛔。
- FLAG_NEW_TASK:
這種調(diào)用方式與在AndroidManifest.xml文檔中申明Activity的launchMode為singleTask產(chǎn)生的效果一樣. - FLAG_Activity_SINGLE_TOP:
這種調(diào)用方式與在AndroidManifest.xml文檔中申明Activity的launchMode為singleTop產(chǎn)生的效果一樣. - FLAG_Activity_CLEAR_TOP:
如果調(diào)用的Activity在當(dāng)前的任務(wù)中存在的話,那么:
a. 如果啟動(dòng)清單文件中啟動(dòng)方式為standard的話漫谷,那么找到該Activity在堆棧中的位置仔雷,將自身和其堆棧上層的所有Activity都o(jì)nDestory()掉,重新在頂層實(shí)例化一個(gè)新的Activity.
b. 如果啟動(dòng)清單文件中啟動(dòng)方式不為standard的話抖剿,那么找到該Activity在堆棧中的位置,將其堆棧上層的所有Activity都o(jì)nDestory()掉识窿,并且通過onNewIntent()恢復(fù)該Activity.
FLAG_Activity_CLEARTOP和FLAG_NEW_TASK經(jīng)常被組合使用斩郎。當(dāng)組合使用時(shí),會(huì)在所有任務(wù)中定位到一個(gè)已經(jīng)存在的Activity,清除包含該Activity的任務(wù)中處于上層的Activity喻频,并在頂層響應(yīng)該Intent缩宜。
處理關(guān)聯(lián)(affinities)
關(guān)聯(lián)(affinity)指一個(gè)Activity所在的任務(wù)。默認(rèn)甥温,同一個(gè)應(yīng)用中的所有Activity都隸屬于同一個(gè)任務(wù)锻煌。然而,可以在AndroidManifest.xml中通過taskAffinity指定一個(gè)關(guān)聯(lián)姻蚓,不同application可以共享一個(gè)關(guān)聯(lián)(任務(wù))宋梧,而同一個(gè)application的不同Activity可以有不同關(guān)聯(lián)。taskAffinity要跟包名不同狰挡,否則就跟默認(rèn)的一樣了.
兩種應(yīng)用場景:
- 以FLAG_Activity_NEW_TASK啟動(dòng)Activity
在以FLAG_ACTIVIY_NEW_TASK啟動(dòng)Activity時(shí)捂龄,如果Activity已經(jīng)在其他的任務(wù)中已經(jīng)啟動(dòng)過了,那么啟動(dòng)改Activity啟動(dòng)時(shí)會(huì)將其他任務(wù)中的Activity帶入到當(dāng)前返回棧中加叁,那么返回的時(shí)候就會(huì)出現(xiàn)其他任務(wù)的Activity倦沧。這時(shí),可以在Activity的AndroidManifest它匕。xml申明時(shí)指定其關(guān)聯(lián)展融,這樣的話,只會(huì)待會(huì)與其關(guān)聯(lián)值一樣的Activity才會(huì)在一個(gè)任務(wù)中豫柬,那么返回退出的時(shí)候就只會(huì)出現(xiàn)關(guān)聯(lián)任務(wù)的Activity.
- 當(dāng)Activity的allowTaskReparenting屬性為true時(shí)
設(shè)置這個(gè)屬性值告希,在當(dāng)前application A的Activity a中啟動(dòng)其他關(guān)聯(lián)的Activity 1后扑浸,當(dāng)A切換到后臺,再重新切回到前臺后暂雹,呈現(xiàn)的是Activity a首装。而Activity 1被重新規(guī)劃到其關(guān)聯(lián)的任務(wù)中。如果有application B的taskAffinity跟Activity1的值一樣的話杭跪,那么可以通過點(diǎn)擊application B后看到Activity 1的界面了仙逻。
返回棧清除
如果用戶離開任務(wù)很長一段時(shí)間,那么系統(tǒng)會(huì)只會(huì)保留任務(wù)中的根Activity而清除其他Activity涧尿。
- alwaysRetainTaskState
為任務(wù)的根Activity設(shè)置為ture的話,那么任務(wù)會(huì)一直保持它的堆棧系奉,即使在很長時(shí)間后。 - clearTaskOnLaunch
這個(gè)是alwaysRetainTaskState屬性的方面姑廉,設(shè)置根Activity的該屬性為true的話缺亮,每次離開任務(wù),再次進(jìn)入任務(wù)都會(huì)從根Activity恢復(fù)桥言。其他的被remove()掉萌踱。 - finishOnTaskLaunch
這個(gè)屬性可以賦值給一個(gè)非根Activity(根Activity是無效的)。如果設(shè)置為true,那么每次重新進(jìn)入任務(wù)都會(huì)remove掉該Activity,摁返回鍵号阿,返回不會(huì)再返回這個(gè)Activity并鸵。
啟動(dòng)任務(wù)
使用MAIN屬性值的action和LAUNCHER的CATEGORY的話,點(diǎn)擊LAUCHER的圖標(biāo)可以啟動(dòng)根Activity進(jìn)而啟動(dòng)任務(wù)。但是LAUNCHER點(diǎn)擊圖標(biāo)還有一個(gè)效果扔涧,即返回任務(wù)园担。試想一下,要是沒有這個(gè)效果枯夜,那每次任務(wù)切換到后臺重新進(jìn)入后弯汰,任務(wù)都沒法恢復(fù)了。