2018-04-11

Android之Activity系列總結(jié)(二)--任務(wù)和返回棧

任務(wù)和返回棧

應(yīng)用通常包含多個(gè)Activity。每個(gè) Activity 均應(yīng)圍繞用戶可以執(zhí)行的特定操作設(shè)計(jì),并且能夠啟動(dòng)其他 Activity。 例如,電子郵件應(yīng)用可能有一個(gè) Activity 顯示新郵件的列表。用戶選擇某郵件時(shí),會(huì)打開一個(gè)新 Activity 以查看該郵件。

一個(gè) Activity 甚至可以啟動(dòng)設(shè)備上其他應(yīng)用中存在的 Activity。例如,如果應(yīng)用想要發(fā)送電子郵件,則可將 Intent 定義為執(zhí)行“發(fā)送”操作并加入一些數(shù)據(jù),如電子郵件地址和電子郵件。 然后,系統(tǒng)將打開其他應(yīng)用中聲明自己處理此類 Intent 的 Activity。在這種情況下,Intent 是要發(fā)送電子郵件,因此將啟動(dòng)電子郵件應(yīng)用的“撰寫”Activity(如果多個(gè) Activity 支持相同 Intent,則系統(tǒng)會(huì)讓用戶選擇要使用的 Activity)。發(fā)送電子郵件時(shí),Activity 將恢復(fù),看起來(lái)好像電子郵件 Activity 是您的應(yīng)用的一部分。 即使這兩個(gè) Activity 可能來(lái)自不同的應(yīng)用,但是 Android 仍會(huì)將 Activity 保留在相同的任務(wù)中,以維護(hù)這種無(wú)縫的用戶體驗(yàn)。

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

設(shè)備主屏幕是大多數(shù)任務(wù)的起點(diǎn)。當(dāng)用戶觸摸應(yīng)用啟動(dòng)器中的圖標(biāo)(或主屏幕上的快捷方式)時(shí),該應(yīng)用的任務(wù)將出現(xiàn)在前臺(tái)。 如果應(yīng)用不存在任務(wù)(應(yīng)用最近未曾使用),則會(huì)創(chuàng)建一個(gè)新任務(wù),并且該應(yīng)用的“主”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)行。 圖 1 通過時(shí)間線顯示 Activity 之間的進(jìn)度以及每個(gè)時(shí)間點(diǎn)的當(dāng)前返回棧,直觀呈現(xiàn)了這種行為。

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

如果用戶繼續(xù)按“返回”,堆棧中的相應(yīng) Activity 就會(huì)彈出,以顯示前一個(gè) Activity,直到用戶返回主屏幕為止(或者,返回任務(wù)開始時(shí)正在運(yùn)行的任意 Activity)。 當(dāng)所有 Activity 均從堆棧中移除后,任務(wù)即不復(fù)存在。

圖 2.兩個(gè)任務(wù):任務(wù) B 在前臺(tái)接收用戶交互,而任務(wù) A 則在后臺(tái)等待恢復(fù)。

圖 3.一個(gè) Activity 將多次實(shí)例化。

任務(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)而已,如圖 2 中所示。然后,任務(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)用?,F(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)丟失。請(qǐng)參閱下面有關(guān)?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 來(lái)自不同的任務(wù)),如圖 3 所示。因此,如果用戶使用“返回”按鈕向后導(dǎo)航,則會(huì)按 Activity 每個(gè)實(shí)例的打開順序顯示這些實(shí)例(每個(gè)實(shí)例的 UI 狀態(tài)各不相同)。 但是,如果您不希望 Activity 多次實(shí)例化,則可修改此行為。 具體操作方法將在后面的管理任務(wù)部分中討論。

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

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

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

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

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

導(dǎo)航設(shè)計(jì)

如需了解有關(guān) Android 應(yīng)用導(dǎo)航工作方式的詳細(xì)信息,請(qǐng)閱讀 Android 設(shè)計(jì)的導(dǎo)航指南。

保存 Activity 狀態(tài)

正如上文所述,當(dāng) Activity 停止時(shí),系統(tǒng)的默認(rèn)行為會(huì)保留其狀態(tài)。 這樣一來(lái),當(dāng)用戶導(dǎo)航回到上一個(gè) Activity 時(shí),其用戶界面與用戶離開時(shí)一樣。 但是,在 Activity 被銷毀且必須重建時(shí),您可以而且應(yīng)當(dāng)主動(dòng)使用回調(diào)方法保留 Activity 的狀態(tài)。

系統(tǒng)停止您的一個(gè) Activity 時(shí)(例如,新 Activity 啟動(dòng)或任務(wù)轉(zhuǎn)到前臺(tái)),如果系統(tǒng)需要回收系統(tǒng)內(nèi)存資源,則可能會(huì)完全銷毀該 Activity。 發(fā)生這種情況時(shí),有關(guān)該 Activity 狀態(tài)的信息將會(huì)丟失。如果發(fā)生這種情況,系統(tǒng)仍會(huì)知道該 Activity 存在于返回棧中,但是當(dāng)該 Activity 被置于堆棧頂部時(shí),系統(tǒng)一定會(huì)重建 Activity(而不是恢復(fù) Activity)。 為了避免用戶的工作丟失,您應(yīng)主動(dòng)通過在 Activity 中實(shí)現(xiàn)onSaveInstanceState()回調(diào)方法來(lái)保留工作。

如需了解有關(guān)如何保存 Activity 狀態(tài)的詳細(xì)信息,請(qǐng)參閱Activity文檔。

管理任務(wù)

Android 管理任務(wù)和返回棧的方式(如上所述,即:將所有連續(xù)啟動(dòng)的 Activity 放入同一任務(wù)和“后進(jìn)先出”堆棧中)非常適用于大多數(shù)應(yīng)用,而您不必?fù)?dān)心 Activity 如何與任務(wù)關(guān)聯(lián)或者如何存在于返回棧中。 但是,您可能會(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。

通過使用清單文件元素中的屬性和傳遞給startActivity()的 Intent 中的標(biāo)志,您可以執(zhí)行所有這些操作以及其他操作。

在這一方面,您可以使用的主要屬性包括:

taskAffinity

launchMode

allowTaskReparenting

clearTaskOnLaunch

alwaysRetainTaskState

finishOnTaskLaunch

您可以使用的主要 Intent 標(biāo)志包括:

FLAG_ACTIVITY_NEW_TASK

FLAG_ACTIVITY_CLEAR_TOP

FLAG_ACTIVITY_SINGLE_TOP

在下文中,您將了解如何使用這些清單文件屬性和 Intent 標(biāo)志定義 Activity 與任務(wù)的關(guān)聯(lián)方式,以及 Activity 在返回棧中的行為方式。

此外,我們還單獨(dú)介紹了有關(guān)如何在概覽屏幕中顯示和管理任務(wù)與 Activity 的注意事項(xiàng)。 如需了解詳細(xì)信息,請(qǐng)參閱概覽屏幕。 通常,您應(yīng)該允許系統(tǒng)定義任務(wù)和 Activity 在概覽屏幕中的顯示方法,并且無(wú)需修改此行為。

注意:大多數(shù)應(yīng)用都不得中斷 Activity 和任務(wù)的默認(rèn)行為: 如果確定您的 Activity 必須修改默認(rèn)行為,當(dāng)使用“返回”按鈕從其他 Activity 和任務(wù)導(dǎo)航回到該 Activity 時(shí),請(qǐng)務(wù)必要謹(jǐn)慎并確保在啟動(dòng)期間測(cè)試該 Activity 的可用性。請(qǐng)確保測(cè)試導(dǎo)航行為是否有可能與用戶的預(yù)期行為沖突。

定義啟動(dòng)模式

啟動(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)模式無(wú)法在清單文件中定義。

使用清單文件

在清單文件中聲明 Activity 時(shí),您可以使用元素的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捻敳?;而堆棧仍?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()之前,用戶無(wú)法按“返回”按鈕返回到 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ù)中打開。

我們?cè)賮?lái)看另一示例,Android 瀏覽器應(yīng)用聲明網(wǎng)絡(luò)瀏覽器 Activity 應(yīng)始終在其自己的任務(wù)中打開(通過在元素中指定singleTask啟動(dòng)模式)。這意味著,如果您的應(yīng)用發(fā)出打開 Android 瀏覽器的 Intent,則其 Activity 與您的應(yīng)用位于不同的任務(wù)中。相反,系統(tǒng)會(huì)為瀏覽器啟動(dòng)新任務(wù),或者如果瀏覽器已有任務(wù)正在后臺(tái)運(yùn)行,則會(huì)將該任務(wù)上移一層以處理新 Intent。

無(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。 圖 4 顯示了這種情況。

圖 4.顯示如何將啟動(dòng)模式為“singleTask”的 Activity 添加到返回棧。 如果 Activity 已經(jīng)是某個(gè)擁有自己的返回棧的后臺(tái)任務(wù)的一部分,則整個(gè)返回棧也會(huì)上移到當(dāng)前任務(wù)的頂部。

如需了解有關(guān)在清單文件中使用啟動(dòng)模式的詳細(xì)信息,請(qǐng)參閱元素文檔,其中更詳細(xì)地討論了launchMode屬性和可接受的值。

:使用launchMode屬性為 Activity 指定的行為可由 Intent 附帶的 Activity 啟動(dòng)標(biāo)志替代,下文將對(duì)此進(jìn)行討論。

使用 Intent 標(biāo)志

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


FLAG_ACTIVITY_NEW_TASK在新任務(wù)中啟動(dòng) Activity。如果已為正在啟動(dòng)的 Activity 運(yùn)行任務(wù),則該任務(wù)會(huì)轉(zhuǎn)到前臺(tái)并恢復(fù)其最后狀態(tài),同時(shí) Activity 會(huì)在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í)例。

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

“關(guān)聯(lián)”指示 Activity 優(yōu)先屬于哪個(gè)任務(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)識(shí)應(yīng)用的默認(rèn)任務(wù)關(guān)聯(lián)。

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

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

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

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

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

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

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

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

清理返回棧

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

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

alwaysRetainTaskState

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

clearTaskOnLaunch

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

finishOnTaskLaunch

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

啟動(dòng)任務(wù)

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


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

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

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

有關(guān)如何在概覽屏幕中顯示和管理任務(wù)與 Activity 的更多信息,請(qǐng)參閱Activity之概覽屏幕(Overview Screen)

?著作權(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)容

  • Android之Activity系列總結(jié)(一)--Activity概覽 Activity 1 創(chuàng)建 Activit...
    我這小樣兒閱讀 231評(píng)論 0 1
  • 【Android Activity】 什么是 Activity? 四大組件之一,通常一個(gè)用戶交互界面對(duì)應(yīng)一個(gè) ac...
    Rtia閱讀 3,927評(píng)論 3 18
  • [文章內(nèi)容來(lái)自Developers]應(yīng)用通常包含多個(gè) Activity。每個(gè) Activity 均應(yīng)圍繞用戶可以執(zhí)...
    岳小川閱讀 756評(píng)論 0 4
  • 任務(wù)和返回棧 應(yīng)用通常包含多個(gè)Activity。每個(gè) Activity 均應(yīng)圍繞用戶可以執(zhí)行的特定操作設(shè)計(jì),并且能...
    xinlingzhiyi閱讀 771評(píng)論 0 6
  • 《為政》包括24章,主要圍繞“為政以德”的思想,如何謀求官職、從政為官的基本原則、學(xué)習(xí)與思考的關(guān)系、孔子本人...
    共剪西窗燭閱讀 1,291評(píng)論 0 0

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