任務(wù)和返回棧

原始文檔

docs/guide/components/tasks-and-back-stack.html

任務(wù)

  1. 任務(wù)(Task)是用戶執(zhí)行特定作業(yè)時(shí)的一系列交互活動(dòng)(Activity)。這些活動(dòng)以打開的順序被存放在堆棧(返回棧)中。
  2. 當(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的操作如下圖所示。


  3. 當(dāng)所有的Activity從棧中移除時(shí),任務(wù)被銷毀。
  4. 返回棧中的所有Activity是不能重新被排序的,這樣的話,如果允許一個(gè)Activity可以被多個(gè)其他Activity啟動(dòng)的話,那么每次會(huì)實(shí)例化一個(gè)Activity,并保存在棧中??梢酝ㄟ^(guò)啟動(dòng)方式來(lái)管理是否每次 都實(shí)例化一個(gè)全新的Activity。
  5. 當(dāng)用戶通過(guò)主頁(yè)按鈕離開當(dāng)前任務(wù),當(dāng)前Activity停止,當(dāng)前任務(wù)進(jìn)入到后臺(tái)。系統(tǒng)會(huì)保持任務(wù)中的每個(gè)Activity的狀態(tài)。當(dāng)用戶通過(guò)點(diǎn)擊啟動(dòng)圖標(biāo),任務(wù)恢復(fù)進(jìn)入前臺(tái),任務(wù)頂端的Activity恢復(fù)狀態(tài)。

Activity狀態(tài)保存

盡管系統(tǒng)會(huì)自動(dòng)保存后臺(tái)的Activity的狀態(tài),但是如果在內(nèi)存緊張的情況下,系統(tǒng)會(huì)銷毀后臺(tái)Activity。這樣的話,一些Activity的重要的信息就會(huì)丟失,在下次改Activity進(jìn)入前臺(tái)的時(shí)候,該意外銷毀的Activity會(huì)被重新創(chuàng)建,無(wú)法恢復(fù)。為避免這種情況的發(fā)生,應(yīng)該主動(dòng)地調(diào)用onSaveInstanceState()來(lái)保存狀態(tài)。

任務(wù)管理

正常的task是一個(gè)“先入后出”的堆棧,每次都實(shí)例一個(gè)Activity并且壓入堆棧。如果想打破這種常規(guī),可以在AndroidManifest.xml的Activity申明啟動(dòng)模式、啟動(dòng)屬性等或者在startActivity()時(shí)指定標(biāo)志位。

清單文件中指定可使用屬性:

  1. taskAffinity (任務(wù)親戚關(guān)系)
  2. launchMode
  3. allowTaskReparenting
  4. clearTaskOnLaunch
  5. alwaysRetainTaskState
  6. finishOnTaskLaunch

Intent標(biāo)志:

  1. FLAG_Activity_NEW_TASK
  2. FLAG_Activity_CLEAR_TOP
  3. FLAG_Activity_SINGLE_TOP

在Intent和清單文件中啟動(dòng)方式發(fā)生沖突時(shí),以Intent中的啟動(dòng)方式為準(zhǔn)

launchMode 啟動(dòng)模式

  1. "standard"
    默認(rèn)啟動(dòng)方式,每次在任務(wù)種實(shí)例化一個(gè)Activity。一個(gè)Activity被實(shí)例化多次,每個(gè)實(shí)例可能隸屬于不同的任務(wù),一個(gè)任務(wù)可能擁有多個(gè)該Activity的實(shí)例。
  2. "singleTop"
    如果返回棧中存在Activity的實(shí)例,并且該實(shí)例在任務(wù)的頂部,那么通過(guò)調(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。
  3. "singleTask"
    所有的任務(wù)(返回棧)中僅能存在一個(gè)實(shí)例。如果所有的任務(wù)中不存在該Activity的實(shí)例,那么實(shí)例化一個(gè)該Activity。如果存在的話,那么進(jìn)入該Activity的onNewIntent()的方法。
    對(duì)于這種啟動(dòng)方式的Activity,對(duì)于返回的處理是比較特殊的。如果從一個(gè)新的任務(wù)中啟動(dòng)一個(gè)其他任務(wù)已存在的Activity,那么相當(dāng)于比之前任務(wù)的返回棧堆疊到到當(dāng)前堆棧上。如下圖所示.
![](http://upload-images.jianshu.io/upload_images/2682632-c754c954576b2822.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

在上圖中Y是singleTask啟動(dòng)方式,Activity2啟動(dòng)Y后,摁返回,不會(huì)立即返回到Activity2,而是按照Y所在的堆棧進(jìn)行返回。如果后臺(tái)任務(wù)順序?yàn)閄-Y-W,那么啟動(dòng)Y的時(shí)候,會(huì)先調(diào)用W.onDestory(),銷毀W,彈出Y。

  1. "singleInstance"
    這種方式是所有任務(wù)中只有一個(gè)Activity實(shí)例,這點(diǎn)跟singleTask是一樣的。所不同的是,該Activity獨(dú)占一個(gè)任務(wù),該任務(wù)不含其他的Activity。

使用Intent標(biāo)志

可以在調(diào)用startActivity()時(shí)指定標(biāo)志位來(lái)指定Activity的啟動(dòng)方式。

  1. FLAG_NEW_TASK:
    這種調(diào)用方式與在AndroidManifest.xml文檔中申明Activity的launchMode為singleTask產(chǎn)生的效果一樣.
  2. FLAG_Activity_SINGLE_TOP:
    這種調(diào)用方式與在AndroidManifest.xml文檔中申明Activity的launchMode為singleTop產(chǎn)生的效果一樣.
  3. 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()掉,并且通過(guò)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中通過(guò)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)用場(chǎng)景

  1. 以FLAG_Activity_NEW_TASK啟動(dòng)Activity

在以FLAG_ACTIVIY_NEW_TASK啟動(dòng)Activity時(shí),如果Activity已經(jīng)在其他的任務(wù)中已經(jīng)啟動(dòng)過(guò)了,那么啟動(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.

  1. 當(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切換到后臺(tái),再重新切回到前臺(tái)后,呈現(xiàn)的是Activity a。而Activity 1被重新規(guī)劃到其關(guān)聯(lián)的任務(wù)中。如果有application B的taskAffinity跟Activity1的值一樣的話,那么可以通過(guò)點(diǎn)擊application B后看到Activity 1的界面了。

返回棧清除

如果用戶離開任務(wù)很長(zhǎng)一段時(shí)間,那么系統(tǒng)會(huì)只會(huì)保留任務(wù)中的根Activity而清除其他Activity。

  1. alwaysRetainTaskState
    為任務(wù)的根Activity設(shè)置為ture的話,那么任務(wù)會(huì)一直保持它的堆棧,即使在很長(zhǎng)時(shí)間后。
  2. clearTaskOnLaunch
    這個(gè)是alwaysRetainTaskState屬性的方面,設(shè)置根Activity的該屬性為true的話,每次離開任務(wù),再次進(jìn)入任務(wù)都會(huì)從根Activity恢復(fù)。其他的被remove()掉。
  3. finishOnTaskLaunch
    這個(gè)屬性可以賦值給一個(gè)非根Activity(根Activity是無(wú)效的)。如果設(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ù)。試想一下,要是沒(méi)有這個(gè)效果,那每次任務(wù)切換到后臺(tái)重新進(jìn)入后,任務(wù)都沒(méi)法恢復(fù)了。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容