Android以任務(wù)的概念來管理Activity的運(yùn)行。任務(wù)是指在執(zhí)行特定作業(yè)時(shí)與用戶交互的一系列 Activity。 這些 Activity 按照各自的打開順序排列在堆棧(即返回棧)中。當(dāng)前 Activity 啟動(dòng)另一個(gè) Activity 時(shí),該新 Activity 會(huì)被推送到堆棧頂部,成為焦點(diǎn)所在。 前一個(gè) Activity 仍保留在堆棧中,但是處于停止?fàn)顟B(tài)。Activity 停止時(shí),系統(tǒng)會(huì)保持其用戶界面的當(dāng)前狀態(tài)。 用戶按“返回”按鈕時(shí),當(dāng)前 Activity 會(huì)從堆棧頂部彈出(Activity 被銷毀),而前一個(gè) Activity 恢復(fù)執(zhí)行(恢復(fù)其 UI 的前一狀態(tài))。 堆棧中的 Activity 永遠(yuǎn)不會(huì)重新排列,僅推入和彈出堆棧:由當(dāng)前 Activity 啟動(dòng)時(shí)推入堆棧;用戶使用“返回”按鈕退出時(shí)彈出堆棧。 因此,返回棧以“后進(jìn)先出”對(duì)象結(jié)構(gòu)運(yùn)行。 下圖通過時(shí)間線顯示 Activity 之間的進(jìn)度以及每個(gè)時(shí)間點(diǎn)的當(dāng)前返回棧,直觀呈現(xiàn)了這種行為。
如果用戶繼續(xù)按“返回”,堆棧中的相應(yīng) Activity 就會(huì)彈出,以顯示前一個(gè) Activity,直到用戶返回主屏幕為止(或者,返回任務(wù)開始時(shí)正在運(yùn)行的任意 Activity)。 當(dāng)所有 Activity 均從堆棧中移除后,任務(wù)即不復(fù)存在。
任務(wù)是一個(gè)有機(jī)整體,當(dāng)用戶開始新任務(wù)或通過“主頁(yè)”按鈕轉(zhuǎn)到主屏幕時(shí),可以移動(dòng)到“后臺(tái)”。 盡管在后臺(tái)時(shí),該任務(wù)中的所有 Activity 全部停止,但是任務(wù)的返回棧仍舊不變,也就是說,當(dāng)另一個(gè)任務(wù)發(fā)生時(shí),該任務(wù)僅僅失去焦點(diǎn)而已,如下圖中所示。然后,任務(wù)可以返回到“前臺(tái)”,用戶就能夠回到離開時(shí)的狀態(tài)。 例如,假設(shè)當(dāng)前任務(wù)(任務(wù) A)的堆棧中有三個(gè) Activity,即當(dāng)前 Activity 下方還有兩個(gè) Activity。 用戶先按“主頁(yè)”按鈕,然后從應(yīng)用啟動(dòng)器啟動(dòng)新應(yīng)用。 顯示主屏幕時(shí),任務(wù) A 進(jìn)入后臺(tái)。新應(yīng)用啟動(dòng)時(shí),系統(tǒng)會(huì)使用自己的 Activity 堆棧為該應(yīng)用啟動(dòng)一個(gè)任務(wù)(任務(wù) B)。與該應(yīng)用交互之后,用戶再次返回主屏幕并選擇最初啟動(dòng)任務(wù) A 的應(yīng)用。現(xiàn)在,任務(wù) A 出現(xiàn)在前臺(tái),其堆棧中的所有三個(gè) Activity 保持不變,而位于堆棧頂部的 Activity 則會(huì)恢復(fù)執(zhí)行。 此時(shí),用戶還可以通過轉(zhuǎn)到主屏幕并選擇啟動(dòng)該任務(wù)的應(yīng)用圖標(biāo)(或者,通過從概覽屏幕選擇該應(yīng)用的任務(wù))切換回任務(wù) B。這是 Android 系統(tǒng)中的一個(gè)多任務(wù)示例。
注:后臺(tái)可以同時(shí)運(yùn)行多個(gè)任務(wù)。但是,如果用戶同時(shí)運(yùn)行多個(gè)后臺(tái)任務(wù),則系統(tǒng)可能會(huì)開始銷毀后臺(tái) Activity,以回收內(nèi)存資源,從而導(dǎo)致 Activity 狀態(tài)丟失。
由于返回棧中的 Activity 永遠(yuǎn)不會(huì)重新排列,因此如果應(yīng)用允許用戶從多個(gè) Activity 中啟動(dòng)特定 Activity,則會(huì)創(chuàng)建該 Activity 的新實(shí)例并推入堆棧中(而不是將 Activity 的任一先前實(shí)例置于頂部)。 因此,應(yīng)用中的一個(gè) Activity 可能會(huì)多次實(shí)例化(即使 Activity 來自不同的任務(wù)),如下圖所示。因此,如果用戶使用“返回”按鈕向后導(dǎo)航,則會(huì)按 Activity 每個(gè)實(shí)例的打開順序顯示這些實(shí)例(每個(gè)實(shí)例的 UI 狀態(tài)各不相同)。 但是,如果不希望 Activity 多次實(shí)例化,則可修改此行為。
Android 管理任務(wù)和返回棧的方式(如上所述,即:將所有連續(xù)啟動(dòng)的 Activity 放入同一任務(wù)和“后進(jìn)先出”堆棧中)非常適用于大多數(shù)應(yīng)用,而不必?fù)?dān)心 Activity 如何與任務(wù)關(guān)聯(lián)或者如何存在于返回棧中。 但是,有時(shí)可能會(huì)決定要中斷正常行為。 也許希望應(yīng)用中的 Activity 在啟動(dòng)時(shí)開始新任務(wù)(而不是放置在當(dāng)前任務(wù)中);或者,當(dāng)啟動(dòng) Activity 時(shí),希望將其現(xiàn)有實(shí)例上移一層(而不是在返回棧的頂部創(chuàng)建新實(shí)例);或者,希望在用戶離開任務(wù)時(shí),清除返回棧中除根 Activity 以外的所有其他 Activity。
通過使用 <activity>
清單文件元素中的屬性和傳遞給 startActivity()
的 Intent 中的標(biāo)志,可以執(zhí)行所有這些操作以及其他操作。
在這一方面,可以使用的主要 <activity>
屬性包括:
taskAffinity
launchMode
allowTaskReparenting
clearTaskOnLaunch
alwaysRetainTaskState
finishOnTaskLaunch
可以使用的主要 Intent 標(biāo)志包括:
FLAG_ACTIVITY_NEW_TASK
FLAG_ACTIVITY_CLEAR_TOP
FLAG_ACTIVITY_SINGLE_TOP
啟動(dòng)模式允許定義 Activity 的新實(shí)例如何與當(dāng)前任務(wù)關(guān)聯(lián)。 可以通過兩種方法定義不同的啟動(dòng)模式:
使用清單文件在清單文件中聲明 Activity 時(shí),可以指定 Activity 在啟動(dòng)時(shí)應(yīng)該如何與任務(wù)關(guān)聯(lián)。
使用 Intent 標(biāo)志調(diào)用 startActivity()
時(shí),可以在 Intent
中加入一個(gè)標(biāo)志,用于聲明新 Activity 如何(或是否)與當(dāng)前任務(wù)關(guān)聯(lián)。
因此,如果 Activity A 啟動(dòng) Activity B,則 Activity B 可以在其清單文件中定義它應(yīng)該如何與當(dāng)前任務(wù)關(guān)聯(lián)(如果可能),并且 Activity A 還可以請(qǐng)求 Activity B 應(yīng)該如何與當(dāng)前任務(wù)關(guān)聯(lián)。如果這兩個(gè) Activity 均定義 Activity B 應(yīng)該如何與任務(wù)關(guān)聯(lián),則 Activity A 的請(qǐng)求(如 Intent 中所定義)優(yōu)先級(jí)要高于 Activity B 的請(qǐng)求(如其清單文件中所定義)。
注:某些適用于清單文件的啟動(dòng)模式不可用作 Intent 標(biāo)志,同樣,某些可用作 Intent 標(biāo)志的啟動(dòng)模式無法在清單文件中定義。
在清單文件中聲明 Activity 時(shí),可以使用 <activity>
元素的 launchMode
屬性指定 Activity 應(yīng)該如何與任務(wù)關(guān)聯(lián)。
launchMode
屬性指定有關(guān)應(yīng)如何將 Activity 啟動(dòng)到任務(wù)中的指令。可以分配給 launchMode
屬性的啟動(dòng)模式共有四種:
"standard"
(默認(rèn)模式)默認(rèn)。系統(tǒng)在啟動(dòng) Activity 的任務(wù)中創(chuàng)建 Activity 的新實(shí)例并向其傳送 Intent。Activity 可以多次實(shí)例化,而每個(gè)實(shí)例均可屬于不同的任務(wù),并且一個(gè)任務(wù)可以擁有多個(gè)實(shí)例。"singleTop"
如果當(dāng)前任務(wù)的頂部已存在 Activity 的一個(gè)實(shí)例,則系統(tǒng)會(huì)通過調(diào)用該實(shí)例的 onNewIntent()
方法向其傳送 Intent,而不是創(chuàng)建 Activity 的新實(shí)例。Activity 可以多次實(shí)例化,而每個(gè)實(shí)例均可屬于不同的任務(wù),并且一個(gè)任務(wù)可以擁有多個(gè)實(shí)例(但前提是位于返回棧頂部的 Activity 并不是 Activity 的現(xiàn)有實(shí)例)。例如,假設(shè)任務(wù)的返回棧包含根 Activity A 以及 Activity B、C 和位于頂部的 D(堆棧是 A-B-C-D;D 位于頂部)。收到針對(duì) D 類 Activity 的 Intent。如果 D 具有默認(rèn)的 "standard"
啟動(dòng)模式,則會(huì)啟動(dòng)該類的新實(shí)例,且堆棧會(huì)變成 A-B-C-D-D。但是,如果 D 的啟動(dòng)模式是 "singleTop"
,則 D 的現(xiàn)有實(shí)例會(huì)通過 onNewIntent()
接收 Intent,因?yàn)樗挥诙褩5捻敳浚欢褩H詾?A-B-C-D。但是,如果收到針對(duì) B 類 Activity 的 Intent,則會(huì)向堆棧添加 B 的新實(shí)例,即便其啟動(dòng)模式為 "singleTop"
也是如此。
注:為某個(gè) Activity 創(chuàng)建新實(shí)例時(shí),用戶可以按“返回”按鈕返回到前一個(gè) Activity。 但是,當(dāng) Activity 的現(xiàn)有實(shí)例處理新 Intent 時(shí),則在新 Intent 到達(dá) onNewIntent()
之前,用戶無法按“返回”按鈕返回到 Activity 的狀態(tài)。
"singleTask"
系統(tǒng)創(chuàng)建新任務(wù)并實(shí)例化位于新任務(wù)底部的 Activity。但是,如果該 Activity 的一個(gè)實(shí)例已存在于一個(gè)單獨(dú)的任務(wù)中,則系統(tǒng)會(huì)通過調(diào)用現(xiàn)有實(shí)例的onNewIntent()
方法向其傳送 Intent,而不是創(chuàng)建新實(shí)例。一次只能存在 Activity 的一個(gè)實(shí)例。注:盡管 Activity 在新任務(wù)中啟動(dòng),但是用戶按“返回”按鈕仍會(huì)返回到前一個(gè) Activity。
"singleInstance"
.與 "singleTask"
相同,只是系統(tǒng)不會(huì)將任何其他 Activity 啟動(dòng)到包含實(shí)例的任務(wù)中。該 Activity 始終是其任務(wù)唯一僅有的成員;由此 Activity 啟動(dòng)的任何 Activity 均在單獨(dú)的任務(wù)中打開。無論 Activity 是在新任務(wù)中啟動(dòng),還是在與啟動(dòng) Activity 相同的任務(wù)中啟動(dòng),用戶按“返回”按鈕始終會(huì)轉(zhuǎn)到前一個(gè) Activity。 但是,如果啟動(dòng)指定singleTask
啟動(dòng)模式的 Activity,則當(dāng)某后臺(tái)任務(wù)中存在該 Activity 的實(shí)例時(shí),整個(gè)任務(wù)都會(huì)轉(zhuǎn)移到前臺(tái)。此時(shí),返回棧包括上移到堆棧頂部的任務(wù)中的所有 Activity。 下圖顯示了這種情況。啟動(dòng) Activity 時(shí),可以通過在傳遞給 startActivity()
的 Intent 中加入相應(yīng)的標(biāo)志,修改 Activity 與其任務(wù)的默認(rèn)關(guān)聯(lián)方式。可用于修改默認(rèn)行為的標(biāo)志包括:
FLAG_ACTIVITY_NEW_TASK
onNewIntent()
中收到新 Intent。正如前文所述,這會(huì)產(chǎn)生與 "singleTask"
launchMode
值相同的行為。
FLAG_ACTIVITY_SINGLE_TOP
如果正在啟動(dòng)的 Activity 是當(dāng)前 Activity(位于返回棧的頂部),則 現(xiàn)有實(shí)例會(huì)接收對(duì) onNewIntent()
的調(diào)用,而不是創(chuàng)建 Activity 的新實(shí)例。正如前文所述,這會(huì)產(chǎn)生與 "singleTop"
launchMode
值相同的行為。
FLAG_ACTIVITY_CLEAR_TOP
如果正在啟動(dòng)的 Activity 已在當(dāng)前任務(wù)中運(yùn)行,則會(huì)銷毀當(dāng)前任務(wù)頂部的所有 Activity,并通過 onNewIntent()
將此 Intent 傳遞給 Activity 已恢復(fù)的實(shí)例(現(xiàn)在位于頂部),而不是啟動(dòng)該 Activity 的新實(shí)例。產(chǎn)生這種行為的 launchMode
屬性沒有值。
FLAG_ACTIVITY_CLEAR_TOP
通常與 FLAG_ACTIVITY_NEW_TASK
結(jié)合使用。一起使用時(shí),通過這些標(biāo)志,可以找到其他任務(wù)中的現(xiàn)有 Activity,并將其放入可從中響應(yīng) Intent 的位置。
注:如果指定 Activity 的啟動(dòng)模式為 "standard"
,則該 Activity 也會(huì)從堆棧中移除,并在其位置啟動(dòng)一個(gè)新實(shí)例,以便處理傳入的 Intent。 這是因?yàn)楫?dāng)啟動(dòng)模式為 "standard"
時(shí),將始終為新 Intent 創(chuàng)建新實(shí)例。
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注