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