Android啟動模式

任務(wù)和返回棧

任務(wù)是指在執(zhí)行特定作業(yè)時與用戶交互的一系列 Activity。 這些 Activity 按照各自的打開順序排列在堆棧(即返回棧)中。

設(shè)備主屏幕是大多數(shù)任務(wù)的起點(diǎn)。當(dāng)用戶觸摸應(yīng)用啟動器中的圖標(biāo)(或主屏幕上的快捷方式)時,該應(yīng)用的任務(wù)將出現(xiàn)在前臺。 如果應(yīng)用不存在任務(wù)(應(yīng)用最近未曾使用),則會創(chuàng)建一個新任務(wù),并且該應(yīng)用的“主”Activity 將作為堆棧中的根 Activity 打開。

圖 1.?顯示任務(wù)中的每個新 Activity 如何向返回棧添加項(xiàng)目。 用戶按“返回”按鈕時,當(dāng)前 Activity 隨即被銷毀,而前一個 Activity 恢復(fù)執(zhí)行。

Activity 和任務(wù)的默認(rèn)行為總結(jié)如下:

當(dāng) Activity A 啟動 Activity B 時,Activity A 將會停止,但系統(tǒng)會保留其狀態(tài)(例如,滾動位置和已輸入表單中的文本)。如果用戶在處于 Activity B 時按“返回”按鈕,則 Activity A 將恢復(fù)其狀態(tài),繼續(xù)執(zhí)行。

用戶通過按“主頁”按鈕離開任務(wù)時,當(dāng)前 Activity 將停止且其任務(wù)會進(jìn)入后臺。 系統(tǒng)將保留任務(wù)中每個 Activity 的狀態(tài)。如果用戶稍后通過選擇開始任務(wù)的啟動器圖標(biāo)來恢復(fù)任務(wù),則任務(wù)將出現(xiàn)在前臺并恢復(fù)執(zhí)行堆棧頂部的 Activity。

如果用戶按“返回”按鈕,則當(dāng)前 Activity 會從堆棧彈出并被銷毀。 堆棧中的前一個 Activity 恢復(fù)執(zhí)行。銷毀 Activity 時,系統(tǒng)不會保留該 Activity 的狀態(tài)。

即使來自其他任務(wù),Activity 也可以多次實(shí)例化。

定義啟動模式

啟動模式允許您定義 Activity 的新實(shí)例如何與當(dāng)前任務(wù)關(guān)聯(lián)。 您可以通過兩種方法定義不同的啟動模式:

使用清單文件?在清單文件中聲明 Activity 時,您可以指定 Activity 在啟動時應(yīng)該如何與任務(wù)關(guān)聯(lián)。

使用 Intent 標(biāo)志?調(diào)用?startActivity()?時,可以在?Intent?中加入一個標(biāo)志,用于聲明新 Activity 如何(或是否)與當(dāng)前任務(wù)關(guān)聯(lián)。

使用清單文件

在清單文件中聲明 Activity 時,您可以使用??元素的?launchMode?屬性指定 Activity 應(yīng)該如何與任務(wù)關(guān)聯(lián)。

launchMode?屬性指定有關(guān)應(yīng)如何將 Activity 啟動到任務(wù)中的指令。您可以分配給?launchMode?屬性的啟動模式共有四種:

"standard"(默認(rèn)模式)

默認(rèn)。系統(tǒng)在啟動 Activity 的任務(wù)中創(chuàng)建 Activity 的新實(shí)例并向其傳送 Intent。Activity 可以多次實(shí)例化,而每個實(shí)例均可屬于不同的任務(wù),并且一個任務(wù)可以擁有多個實(shí)例。

"singleTop"

如果當(dāng)前任務(wù)的頂部已存在 Activity 的一個實(shí)例,則系統(tǒng)會通過調(diào)用該實(shí)例的?onNewIntent()?方法向其傳送 Intent,而不是創(chuàng)建 Activity 的新實(shí)例。Activity 可以多次實(shí)例化,而每個實(shí)例均可屬于不同的任務(wù),并且一個任務(wù)可以擁有多個實(shí)例(但前提是位于返回棧頂部的 Activity 并不是 Activity 的現(xiàn)有實(shí)例)。

例如,假設(shè)任務(wù)的返回棧包含根 Activity A 以及 Activity B、C 和位于頂部的 D(堆棧是 A-B-C-D;D 位于頂部)。收到針對 D 類 Activity 的 Intent。如果 D 具有默認(rèn)的?"standard"?啟動模式,則會啟動該類的新實(shí)例,且堆棧會變成 A-B-C-D-D。但是,如果 D 的啟動模式是?"singleTop",則 D 的現(xiàn)有實(shí)例會通過?onNewIntent()?接收 Intent,因?yàn)樗挥诙褩5捻敳?;而堆棧仍?A-B-C-D。但是,如果收到針對 B 類 Activity 的 Intent,則會向堆棧添加 B 的新實(shí)例,即便其啟動模式為?"singleTop"?也是如此。

"singleTask"

系統(tǒng)創(chuàng)建新任務(wù)并實(shí)例化位于新任務(wù)底部的 Activity。但是,如果該 Activity 的一個實(shí)例已存在于一個單獨(dú)的任務(wù)中,則系統(tǒng)會通過調(diào)用現(xiàn)有實(shí)例的onNewIntent()?方法向其傳送 Intent,而不是創(chuàng)建新實(shí)例。一次只能存在 Activity 的一個實(shí)例。

"singleInstance".

與?"singleTask"?相同,只是系統(tǒng)不會將任何其他 Activity 啟動到包含實(shí)例的任務(wù)中。該 Activity 始終是其任務(wù)唯一僅有的成員;由此 Activity 啟動的任何 Activity 均在單獨(dú)的任務(wù)中打開。

使用 Intent 標(biāo)志

啟動 Activity 時,您可以通過在傳遞給?startActivity()?的 Intent 中加入相應(yīng)的標(biāo)志,修改 Activity 與其任務(wù)的默認(rèn)關(guān)聯(lián)方式??捎糜谛薷哪J(rèn)行為的標(biāo)志包括:

FLAG_ACTIVITY_NEW_TASK

在新任務(wù)中啟動 Activity。如果已為正在啟動的 Activity 運(yùn)行任務(wù),則該任務(wù)會轉(zhuǎn)到前臺并恢復(fù)其最后狀態(tài),同時 Activity 會在?onNewIntent()?中收到新 Intent。

正如前文所述,這會產(chǎn)生與?"singleTask"launchMode?值相同的行為。

FLAG_ACTIVITY_SINGLE_TOP

如果正在啟動的 Activity 是當(dāng)前 Activity(位于返回棧的頂部),則 現(xiàn)有實(shí)例會接收對?onNewIntent()?的調(diào)用,而不是創(chuàng)建 Activity 的新實(shí)例。

正如前文所述,這會產(chǎn)生與?"singleTop"launchMode?值相同的行為。

FLAG_ACTIVITY_CLEAR_TOP

如果正在啟動的 Activity 已在當(dāng)前任務(wù)中運(yùn)行,則會銷毀當(dāng)前任務(wù)頂部的所有 Activity,并通過?onNewIntent()?將此 Intent 傳遞給 Activity 已恢復(fù)的實(shí)例(現(xiàn)在位于頂部),而不是啟動該 Activity 的新實(shí)例。

產(chǎn)生這種行為的?launchMode?屬性沒有值。

FLAG_ACTIVITY_CLEAR_TOP?通常與?FLAG_ACTIVITY_NEW_TASK?結(jié)合使用。一起使用時,通過這些標(biāo)志,可以找到其他任務(wù)中的現(xiàn)有 Activity,并將其放入可從中響應(yīng) Intent 的位置。

:如果指定 Activity 的啟動模式為?"standard",則該 Activity 也會從堆棧中移除,并在其位置啟動一個新實(shí)例,以便處理傳入的 Intent。 這是因?yàn)楫?dāng)啟動模式為?"standard"?時,將始終為新 Intent 創(chuàng)建新實(shí)例。

處理關(guān)聯(lián)

“關(guān)聯(lián)”指示 Activity 優(yōu)先屬于哪個任務(wù)。默認(rèn)情況下,同一應(yīng)用中的所有 Activity 彼此關(guān)聯(lián)。 因此,默認(rèn)情況下,同一應(yīng)用中的所有 Activity 優(yōu)先位于相同任務(wù)中。 不過,您可以修改 Activity 的默認(rèn)關(guān)聯(lián)。 在不同應(yīng)用中定義的 Activity 可以共享關(guān)聯(lián),或者可為在同一應(yīng)用中定義的 Activity 分配不同的任務(wù)關(guān)聯(lián)。

可以使用??元素的?taskAffinity?屬性修改任何給定 Activity 的關(guān)聯(lián)。

taskAffinity?屬性取字符串值,該值必須不同于在元素中聲明的默認(rèn)軟件包名稱,因?yàn)橄到y(tǒng)使用該名稱標(biāo)識應(yīng)用的默認(rèn)任務(wù)關(guān)聯(lián)。

在兩種情況下,關(guān)聯(lián)會起作用:

啟動 Activity 的 Intent 包含?FLAG_ACTIVITY_NEW_TASK?標(biāo)志。

默認(rèn)情況下,新 Activity 會啟動到調(diào)用?startActivity()?的 Activity 任務(wù)中。它將推入與調(diào)用方相同的返回棧。 但是,如果傳遞給startActivity()?的 Intent 包含?FLAG_ACTIVITY_NEW_TASK?標(biāo)志,則系統(tǒng)會尋找其他任務(wù)來儲存新 Activity。這通常是新任務(wù),但未做強(qiáng)制要求。 如果現(xiàn)有任務(wù)與新 Activity 具有相同關(guān)聯(lián),則會將 Activity 啟動到該任務(wù)中。 否則,將開始新任務(wù)。

如果此標(biāo)志導(dǎo)致 Activity 開始新任務(wù),且用戶按“主頁”按鈕離開,則必須為用戶提供導(dǎo)航回任務(wù)的方式。 有些實(shí)體(如通知管理器)始終在外部任務(wù)中啟動 Activity,而從不作為其自身的一部分啟動 Activity,因此它們始終將?FLAG_ACTIVITY_NEW_TASK?放入傳遞給?startActivity()?的 Intent 中。請注意,如果 Activity 能夠由可以使用此標(biāo)志的外部實(shí)體調(diào)用,則用戶可以通過獨(dú)立方式返回到啟動的任務(wù),例如,使用啟動器圖標(biāo)(任務(wù)的根 Activity 具有?CATEGORY_LAUNCHER?Intent 過濾器;請參閱下面的啟動任務(wù)部分)。

Activity 將其?allowTaskReparenting?屬性設(shè)置為?"true"。

在這種情況下,Activity 可以從其啟動的任務(wù)移動到與其具有關(guān)聯(lián)的任務(wù)(如果該任務(wù)出現(xiàn)在前臺)。

例如,假設(shè)將報告所選城市天氣狀況的 Activity 定義為旅行應(yīng)用的一部分。 它與同一應(yīng)用中的其他 Activity 具有相同的關(guān)聯(lián)(默認(rèn)應(yīng)用關(guān)聯(lián)),并允許利用此屬性重定父級。當(dāng)您的一個 Activity 啟動天氣預(yù)報 Activity 時,它最初所屬的任務(wù)與您的 Activity 相同。 但是,當(dāng)旅行應(yīng)用的任務(wù)出現(xiàn)在前臺時,系統(tǒng)會將天氣預(yù)報 Activity 重新分配給該任務(wù)并顯示在其中。

提示:如果從用戶的角度來看,一個?.apk?文件包含多個“應(yīng)用”,則您可能需要使用?taskAffinity?屬性將不同關(guān)聯(lián)分配給與每個“應(yīng)用”相關(guān)的 Activity。

清理返回棧

如果用戶長時間離開任務(wù),則系統(tǒng)會清除所有 Activity 的任務(wù),根 Activity 除外。 當(dāng)用戶再次返回到任務(wù)時,僅恢復(fù)根 Activity。系統(tǒng)這樣做的原因是,經(jīng)過很長一段時間后,用戶可能已經(jīng)放棄之前執(zhí)行的操作,返回到任務(wù)是要開始執(zhí)行新的操作。

您可以使用下列幾個 Activity 屬性修改此行為:

alwaysRetainTaskState

如果在任務(wù)的根 Activity 中將此屬性設(shè)置為?"true",則不會發(fā)生剛才所述的默認(rèn)行為。即使在很長一段時間后,任務(wù)仍將所有 Activity 保留在其堆棧中。

clearTaskOnLaunch

如果在任務(wù)的根 Activity 中將此屬性設(shè)置為?"true",則每當(dāng)用戶離開任務(wù)然后返回時,系統(tǒng)都會將堆棧清除到只剩下根 Activity。 換而言之,它與alwaysRetainTaskState?正好相反。 即使只離開任務(wù)片刻時間,用戶也始終會返回到任務(wù)的初始狀態(tài)。

finishOnTaskLaunch

此屬性類似于?clearTaskOnLaunch,但它對單個 Activity 起作用,而非整個任務(wù)。 此外,它還有可能會導(dǎo)致任何 Activity 停止,包括根 Activity。 設(shè)置為?"true"?時,Activity 仍是任務(wù)的一部分,但是僅限于當(dāng)前會話。如果用戶離開然后返回任務(wù),則任務(wù)將不復(fù)存在。

啟動任務(wù)

通過為 Activity 提供一個以?"android.intent.action.MAIN"?為指定操作、以?"android.intent.category.LAUNCHER"?為指定類別的 Intent 過濾器,您可以將 Activity 設(shè)置為任務(wù)的入口點(diǎn)。

此類 Intent 過濾器會使 Activity 的圖標(biāo)和標(biāo)簽顯示在應(yīng)用啟動器中,讓用戶能夠啟動 Activity 并在啟動之后隨時返回到創(chuàng)建的任務(wù)中。

第二個功能非常重要:用戶必須能夠在離開任務(wù)后,再使用此 Activity 啟動器返回該任務(wù)。 因此,只有在 Activity 具有?ACTION_MAIN?和?CATEGORY_LAUNCHER?過濾器時,才應(yīng)該使用將 Activity 標(biāo)記為“始終啟動任務(wù)”的兩種啟動模式,即?"singleTask"?和?"singleInstance"。例如,我們可以想像一下如果缺少過濾器會發(fā)生什么情況: Intent 啟動一個?"singleTask"?Activity,從而啟動一個新任務(wù),并且用戶花了些時間處理該任務(wù)。然后,用戶按“主頁”按鈕。 任務(wù)現(xiàn)已發(fā)送到后臺,而且不可見。現(xiàn)在,用戶無法返回到任務(wù),因?yàn)樵撊蝿?wù)未顯示在應(yīng)用啟動器中。

如果您并不想用戶能夠返回到 Activity,對于這些情況,請將??元素的?finishOnTaskLaunch?設(shè)置為?"true"(請參閱清理堆棧

查看task棧情況

在cmd命令行里或者Android Studio中的Terminal里敲入如下命令:

adb shell dumpsys activity activities

官方文檔的摘抄

參考:

任務(wù)和返回棧

使用Adb shell dumpsys檢測Android的Activity任務(wù)棧

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

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

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,062評論 25 709
  • 1. 基本介紹 大家平時只要懂一點(diǎn)Android知識的話,都一定會知道,一個應(yīng)用的組成,往往包含了許多的activ...
    fitchzheng閱讀 541評論 0 0
  • 在這篇文章中,我會繼續(xù)跟大家分享有關(guān)于Android中啟動模式的相關(guān)知識。當(dāng)然,如果對這個啟動模式還不完全了解或者...
    fitchzheng閱讀 2,555評論 2 1
  • 在介紹 Android 啟動模式之前,先介紹兩個概念,一個是 task ,另一個是在 Androidmanifes...
    Utopia_Sen閱讀 1,472評論 0 6
  • 可能是我們85后的一輩都開始“老了”,以前在QQ空間曬的都是去哪玩、秀幸福、秀豪車、秀有錢,現(xiàn)在的微信朋友圈...
    幸福貓閱讀 175評論 0 0

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