Activity 啟動(dòng)模式全解析

Activity 啟動(dòng)模式全解析

一、任務(wù)與返回棧 (Tasks and Back Stack)

任務(wù)的定義:執(zhí)行特定作業(yè)時(shí)與用戶交互的一系列 Activity。這些 Activity 按照各自的打開(kāi)順序排列在堆棧(即返回棧)中,堆棧頂部 Activity 即為可見(jiàn)的界面。堆棧中的 Activity 永遠(yuǎn)不會(huì) 重新排列,僅推入(push)和彈出(pop)堆棧:由當(dāng)前 Activity 啟動(dòng)時(shí)推入堆棧;用戶使用 Back 按鈕退出時(shí)彈出堆棧。當(dāng)所有 Activity 均從堆棧中移除后,任務(wù)即不復(fù)存在。

舉個(gè)例子,Contacts 應(yīng)用的 PeopleActivity 可以啟動(dòng) QuickContactActivity 來(lái)查看聯(lián)系人信息,而 QuickContactActivity 可以通過(guò) Intent 啟動(dòng) Email 應(yīng)用的編寫(xiě)郵件的 Activity。雖然 Activity 來(lái)自不同的應(yīng)用,但是它們都被保留在相同的任務(wù)中以保持無(wú)縫的用戶體驗(yàn):用戶按 Back 鍵時(shí),會(huì)逐個(gè)回退到上一個(gè) Activity,仿佛這些 Activity 是屬于同一個(gè)應(yīng)用的。

任務(wù)作為一個(gè)整體而存在,簡(jiǎn)單來(lái)說(shuō)就是在某個(gè) Activity 按 Home 鍵之后,該 Activity 所在的任務(wù)就被移到后臺(tái),但任務(wù)的返回棧不變。切換回這個(gè) Activity 后,按 Back 鍵可以發(fā)現(xiàn)回退到了堆棧的上一個(gè) Activity?;谌蝿?wù)與其返回棧的關(guān)系,我們使用任務(wù)棧來(lái)表達(dá)其含義。

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

當(dāng) Activity A 啟動(dòng) Activity B 時(shí),

  • Activity A 將會(huì)停止,但系統(tǒng)會(huì)保留其狀態(tài)(例如,滾動(dòng)位置和已輸入表單中的文本)。
  • 創(chuàng)建 Activity B 的實(shí)例并向其傳送 Intent,其將被推入 Activity A 的任務(wù)棧中。

處于 Activity B 時(shí)按 Back 按鈕

  • 當(dāng)前 Activity B 會(huì)從堆棧彈出并被銷(xiāo)毀。銷(xiāo)毀 Activity 時(shí),系統(tǒng)不會(huì)保留該 Activity 的狀態(tài)。
  • 堆棧中的前一個(gè) Activity A 恢復(fù)其狀態(tài),繼續(xù)執(zhí)行。

用戶通過(guò)按 Home 按鈕離開(kāi)任務(wù)時(shí),

  • 當(dāng)前 Activity 將停止且其任務(wù)會(huì)進(jìn)入后臺(tái)。
  • 系統(tǒng)將保留任務(wù)中每個(gè) Activity 的狀態(tài)。

選擇開(kāi)始任務(wù)的啟動(dòng)器圖標(biāo)來(lái)恢復(fù)任務(wù),

  • 任務(wù)將出現(xiàn)在前臺(tái)并恢復(fù)執(zhí)行堆棧頂部的 Activity。
  • 如果用戶長(zhǎng)時(shí)間離開(kāi)任務(wù),則系統(tǒng)會(huì)清除任務(wù)棧中除根 Activity 之外的所有 Activity。當(dāng)用戶再次返回到任務(wù)時(shí),僅恢復(fù)根 Activity。

二、管理任務(wù)

上面提到的默認(rèn)行為適用于大多數(shù)的 Activity,不需要額外的設(shè)置即可滿足應(yīng)用的需要。但有時(shí)候需要打破這種默認(rèn)的行為,比如,打開(kāi)應(yīng)用的第一個(gè) Activity A,然后用戶注冊(cè)經(jīng)過(guò)了一個(gè)或多個(gè) Activity,注冊(cè)完成后回到第一個(gè) Activity A,如果按照默認(rèn)的行為,堆棧中將會(huì)實(shí)例化兩個(gè) Activity A,而且這兩個(gè)之間還包含了注冊(cè)用的 Activity,這樣子在用戶 Back 鍵想退出應(yīng)用的時(shí)候,就會(huì)跳轉(zhuǎn)到不想要跳轉(zhuǎn)到的注冊(cè)用的 Activity,這就要求回到 Activity A 時(shí)清除注冊(cè)用的 Activity?;蛘撸_(kāi)發(fā)者希望用戶不論在哪個(gè) Activity 切換到后臺(tái)時(shí),再開(kāi)啟應(yīng)用時(shí)要從應(yīng)用的第一個(gè) Activity 開(kāi)始。

這些不符合默認(rèn)行為的操作可以通過(guò)指定 Manifest 文件中 <activity> 元素中的屬性和傳遞給 startActivity() 的 Intent 中的標(biāo)志來(lái)完成設(shè)置。

注意: 應(yīng)用大多數(shù)情況下都不必改變 Activity 和任務(wù)的默認(rèn)行為;如果確定必須修改默認(rèn)行為,請(qǐng)測(cè)試使用 Back 按鈕從其他 Activity 或從 Recent 界面回到該 Activity 時(shí)的行為,確認(rèn)應(yīng)用的行為是否有可能與用戶的預(yù)期行為沖突。

在清單文件中聲明 Activity 時(shí),可以指定 Activity 在啟動(dòng)時(shí)應(yīng)該如何與任務(wù)關(guān)聯(lián)??梢允褂玫?<activity> 屬性有:

  • launchMode
  • taskAffinity
  • allowTaskReparenting
  • clearTaskOnLaunch
  • alwaysRetainTaskState
  • finishOnTaskLaunch

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

  • FLAG_ACTIVITY_NEW_TASK
  • FLAG_ACTIVITY_CLEAR_TOP
  • FLAG_ACTIVITY_SINGLE_TOP

如果 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)求(如其清單文件中所定義)。

我們將屬性分為兩組:

  1. 改變?nèi)蝿?wù)啟動(dòng) Activity 時(shí)的默認(rèn)行為
  • launchMode
  • taskAffinity
  • allowTaskReparenting
  1. 改變?nèi)蝿?wù)恢復(fù) Activity 時(shí)的默認(rèn)行為
  • clearTaskOnLaunch
  • alwaysRetainTaskState
  • finishOnTaskLaunch

1. 改變?nèi)蝿?wù)啟動(dòng) Activity 時(shí)的默認(rèn)行為

1.1. launchMode 和 taskAffinity

launchMode 包括了四種屬性值:standard (默認(rèn)模式)、singleTop、singleTask、singleInstance。相應(yīng)的,使用 FLAG_ACTIVITY_SINGLE_TOP 標(biāo)志產(chǎn)生與 singleTop 相同的行為,而FLAG_ACTIVITY_NEW_TASKFLAG_ACTIVITY_CLEAR_TOP 一般一起使用,產(chǎn)生與 singleTask 相同的行為,一般不單獨(dú)使用,因?yàn)閱为?dú)使用常常導(dǎo)致奇怪的效果。

taskAffinity 指示 Activity 優(yōu)先屬于哪個(gè)任務(wù)。默認(rèn)情況下,同一應(yīng)用中的所有 Activity 默認(rèn)使用軟件包名稱彼此關(guān)聯(lián)。在不同應(yīng)用中定義的 Activity 可以共享關(guān)聯(lián),或者可為在同一應(yīng)用中定義的 Activity 分配不同的任務(wù)關(guān)聯(lián)。taskAffinity 僅在兩種情況下起作用:一是 Activity 的 launchMode 為 singleTask(即以 FLAG_ACTIVITY_NEW_TASK 的 Intent 啟動(dòng)的應(yīng)用);一是 Activity 將其 allowTaskReparenting 屬性設(shè)置為 "true"。

以下我們將分別解釋 launchMode 的行為及對(duì)其進(jìn)行測(cè)試分析。測(cè)試所用的應(yīng)用代碼在這里。

1.1.1. standard (默認(rèn)模式)

系統(tǒng)在啟動(dòng) Activity 的任務(wù)中創(chuàng)建被啟用的 Activity 的新實(shí)例并向其傳送 Intent。Activity 可以多次實(shí)例化,而每個(gè)實(shí)例可屬于不同的任務(wù)或者一個(gè)任務(wù)可以擁有多個(gè)實(shí)例。

測(cè)試 1:

MainActivity --> StandardActivity --> StandardActivity --> StandardActivity

結(jié)果:

************* onCreate *************
MainActivity TaskId: 1189 HashCode:241879363
taskAffinity:com.mupceet.activitytaskdemo
************* onCreate *************
StandardActivity TaskId: 1189 HashCode:64163597
taskAffinity:com.mupceet.activitytaskdemo
************* onCreate *************
StandardActivity TaskId: 1189 HashCode:60617326
taskAffinity:com.mupceet.activitytaskdemo
************* onCreate *************
StandardActivity TaskId: 1189 HashCode:227576965
taskAffinity:com.mupceet.activitytaskdemo

解析:

結(jié)論 來(lái)源
Activity 由 A 啟動(dòng)則它與 A 存在于同一任務(wù)棧中 TaskId 相同
每次啟動(dòng) Activity 都會(huì)創(chuàng)建一個(gè)新的實(shí)例 StandardActivity 創(chuàng)建時(shí)走 onCreate 方法,HashCode 不相同

1.1.2. singleTop

如果當(dāng)前任務(wù)棧的棧頂為 Activity 的一個(gè)實(shí)例,則系統(tǒng)會(huì)通過(guò)調(diào)用該實(shí)例的 onNewIntent() 方法向其傳送 Intent,而不是創(chuàng)建 Activity 的新實(shí)例。但如果棧頂?shù)?Activity 并不是 Activity 的現(xiàn)有實(shí)例,Activity 的表現(xiàn)與 standard 模式相同。

注: 為某個(gè) Activity 創(chuàng)建新實(shí)例時(shí),用戶可以按 Back 按鈕返回到前一個(gè) Activity。 但是,當(dāng) Activity 的現(xiàn)有實(shí)例處理新 Intent 時(shí),則在新 Intent 到達(dá) onNewIntent() 之前,用戶無(wú)法按 Back 按鈕返回到 Activity 的狀態(tài)。

測(cè)試 2:SingleTopActivity 啟動(dòng)后處于棧頂

MainActivity --> SingleTopActivity --> SingleTopActivity --> SingleTopActivity

結(jié)果:

************* onCreate *************
MainActivity TaskId: 1190 HashCode:242719467
taskAffinity:com.mupceet.activitytaskdemo
************* onCreate *************
SingleTopActivity TaskId: 1190 HashCode:122301260
taskAffinity:com.mupceet.activitytaskdemo
************* onNewIntent *************
SingleTopActivity TaskId: 1190 HashCode:122301260
taskAffinity:com.mupceet.activitytaskdemo
************* onNewIntent *************
SingleTopActivity TaskId: 1190 HashCode:122301260
taskAffinity:com.mupceet.activitytaskdemo

解析:

結(jié)論 來(lái)源
Activity 由 A 啟動(dòng)則它與 A 存在于同一任務(wù)棧中 TaskId 相同
第一次啟動(dòng) Activity 會(huì)創(chuàng)建一個(gè)實(shí)例 第一次啟動(dòng) SingleTopActivity 時(shí)運(yùn)行 onCreate 方法
多次啟動(dòng) Activity (處于棧頂) 只會(huì)回調(diào) onNewIntent 方法 啟動(dòng) SingleTopActivity 后,再多次啟動(dòng) SingleTopActivity,Intent 由 onNewIntent 處理,且 HashCode 相同

測(cè)試 3:SingleTopActivity 啟動(dòng)后不處于棧頂

MainActivity --> SingleTopActivity --> OtherTopActivity --> SingleTopActivity

結(jié)果:

************* onCreate *************
MainActivity TaskId: 1191 HashCode:145258514
taskAffinity:com.mupceet.activitytaskdemo
************* onCreate *************
SingleTopActivity TaskId: 1191 HashCode:9399791
taskAffinity:com.mupceet.activitytaskdemo
************* onCreate *************
OtherTopActivity TaskId: 1191 HashCode:209949367
taskAffinity:com.mupceet.activitytaskdemo
************* onCreate *************
SingleTopActivity TaskId: 1191 HashCode:48271010
taskAffinity:com.mupceet.activitytaskdemo

解析:

結(jié)論 來(lái)源
再次啟動(dòng) Activity (不處于棧頂) 會(huì)創(chuàng)建一個(gè)新實(shí)例 第二次啟動(dòng) SingleTopActivity,運(yùn)行 onCreate 方法,且 HashCode 不相同

1.1.3. singleTask

系統(tǒng)不存在該任務(wù)(taskAffinity 標(biāo)識(shí)的任務(wù)名)則創(chuàng)建新任務(wù)并實(shí)例化 Activity 推入任務(wù)棧底。如果存在任務(wù),但沒(méi)有實(shí)例,將實(shí)例化 Activity 并推入任務(wù)棧,但是,如果該 Activity 的一個(gè)實(shí)例已存在于任務(wù)中,則系統(tǒng)會(huì)通過(guò)調(diào)用現(xiàn)有實(shí)例的 onNewIntent() 方法向其傳送 Intent,并且原來(lái)?xiàng)V刑幱?Activity 之上的被清理出棧。即任務(wù)棧中只能存在 Activity 的一個(gè)實(shí)例。

注: 盡管 Activity 在新 Task 中啟動(dòng),但是用戶按 Back 按鈕仍會(huì)返回到前一個(gè) Activity。

測(cè)試 4:SingleTaskActivity 不指定 taskAffinity

MainActivity --> SingleTaskActivity --> OtherTaskActivity --> SingleTaskActivity

結(jié)果:

************* onCreate *************
MainActivity TaskId: 1192 HashCode:160080556
taskAffinity:com.mupceet.activitytaskdemo
************* onCreate *************
SingleTaskActivity TaskId: 1192 HashCode:125240432
taskAffinity:com.mupceet.activitytaskdemo
************* onCreate *************
OtherTaskActivity TaskId: 1192 HashCode:35483478
taskAffinity:com.mupceet.activitytaskdemo
************* onNewIntent *************
SingleTaskActivity TaskId: 1192 HashCode:125240432
taskAffinity:com.mupceet.activitytaskdemo
Running activities (most recent first):
  TaskRecord{216074a #1218 A=com.mupceet.activitytaskdemo U=0 StackId=1 sz=2}
    Run #1: ActivityRecord{8ca4bea u0 com.mupceet.activitytaskdemo/.SingleTaskActivity t1218}
    Run #0: ActivityRecord{5a6a171 u0 com.mupceet.activitytaskdemo/.MainActivity t1218}

解析:

結(jié)論 來(lái)源
Activity 由 A 啟動(dòng)則它與 A 存在于同一任務(wù)棧中 TaskId 相同
再次啟動(dòng) Activity 會(huì)回調(diào) onNewIntent 方法 再次啟動(dòng) SingleTaskActivity,Intent 由 onNewIntent 處理,且 HashCode 相同
原來(lái)?xiàng)V刑幱?Activity 之上的被清理出棧 再次啟動(dòng) SingleTaskActivity 后,棧中僅有兩個(gè) Activity

測(cè)試 5:SingleTaskActivity 指定 taskAffinity

MainActivity --> SingleTaskActivityWithAffinity --> StandardActivity

結(jié)果:

************* onCreate *************
MainActivity TaskId: 1200 HashCode:176168109
taskAffinity:com.mupceet.activitytaskdemo
************* onCreate *************
SingleTaskActivityWithAffinity TaskId: 1201 HashCode:95759438
taskAffinity:com.mupceet.task2
************* onCreate *************
StandardActivity TaskId: 1201 HashCode:233514981
taskAffinity:com.mupceet.activitytaskdemo

解析:

結(jié)論 來(lái)源
Activity 啟動(dòng)到新的任務(wù)棧中 MainActivity 與 SingleTaskActivityWithAffinity 的 TaskId 不相同
Activity 啟動(dòng) standard 模式的 Activity 處于同一任務(wù)棧 啟動(dòng) StandardActivity,兩者的 TaskId 相同

測(cè)試 6:SingleTaskActivity 和 OtherActivity 指定相同 taskAffinity

(TaskDemo) MainActivity --> SingleTaskActivityWithAffinity --> home 返回主頁(yè)
(TaskDemo2) MainActivity --> OtherActivityWithAffinity

結(jié)果:

************* onCreate *************
MainActivity TaskId: 1202 HashCode:8042982
taskAffinity:com.mupceet.activitytaskdemo
************* onCreate *************
SingleTaskActivityWithAffinity TaskId: 1203 HashCode:37289106
taskAffinity:com.mupceet.task2

************* onCreate *************
MainActivity TaskId: 1204 HashCode:241879363
taskAffinity:com.mupceet.activitytaskdemo2
************* onCreate *************
OtherActivityWithActivity TaskId: 1203 HashCode:186496063
taskAffinity:com.mupceet.task2
Running activities (most recent first):
      TaskRecord{5d38658 #1203 A=com.mupceet.task2 U=0 StackId=1 sz=2}
        Run #3: ActivityRecord{f653f3 u0 com.mupceet.activitytaskdemo2/.OtherActivityWithActivity t1203}
      TaskRecord{532c417 #1204 A=com.mupceet.activitytaskdemo2 U=0 StackId=1 sz=1}
        Run #2: ActivityRecord{2a6ae8b u0 com.mupceet.activitytaskdemo2/.MainActivity t1204}
      TaskRecord{5d38658 #1203 A=com.mupceet.task2 U=0 StackId=1 sz=2}
        Run #1: ActivityRecord{6ebc71c u0 com.mupceet.activitytaskdemo/.SingleTaskActivityWithAffinity t1203}
      TaskRecord{43259ed #1202 A=com.mupceet.activitytaskdemo U=0 StackId=1 sz=1}
        Run #0: ActivityRecord{df97ca7 u0 com.mupceet.activitytaskdemo/.MainActivity t1202}

解析:

結(jié)論 來(lái)源
Activity 啟動(dòng)到新的任務(wù)棧中 MainActivity 與 SingleTaskActivityWithAffinity 的 TaskId 不相同
具有相同 taskAffinity 的 Activity 啟動(dòng)后將處于同一任務(wù)棧 SingleTaskActivityWithAffinity 與 OtherActivityWithActivity 的 TaskId 相同

注意,這里有個(gè)現(xiàn)象需要注意,即如果存在任務(wù),但沒(méi)有實(shí)例,將實(shí)例化 Activity 并推入任務(wù)棧,這個(gè)任務(wù)棧就在前臺(tái)運(yùn)行,此時(shí)按 Back 鍵得直到此任務(wù)棧清空后才會(huì)回到啟動(dòng)該 Activity 的那個(gè)任務(wù)棧,而不是像平常一次返回就可以返回啟動(dòng) Activity。如果不明白這段話,只要將測(cè)試 6 的步驟改動(dòng)一下為:

(TaskDemo) MainActivity --> SingleTaskActivityWithAffinity --> StandardActivity --> StandardActivity --> home 返回主頁(yè)
(TaskDemo2) MainActivity --> OtherActivityWithAffinity

再點(diǎn)擊幾次 Back 鍵就知道是什么意思

1.1.4. singleInstance

與 "singleTask" 類(lèi)似,但系統(tǒng)不會(huì)將任何其他 Activity 啟動(dòng)到包含該 Activity 實(shí)例的任務(wù)棧中。即該 Activity 始終是其任務(wù)棧唯一僅有的成員;由此 Activity 啟動(dòng)的任何 Activity 均在其他的任務(wù)中打開(kāi)。

測(cè)試 7:

MainActivity--> SingleInstanceActivity--> MainActivity--> SingleInstanceActivity

結(jié)果:

************* onCreate *************
MainActivity TaskId: 1194 HashCode:19028065
taskAffinity:com.mupceet.activitytaskdemo
************* onCreate *************
SingleInstanceActivity TaskId: 1195 HashCode:109601484
taskAffinity:com.mupceet.activitytaskdemo
************* onCreate *************
MainActivity TaskId: 1194 HashCode:202770375
taskAffinity:com.mupceet.activitytaskdemo
************* onNewIntent *************
SingleInstanceActivity TaskId: 1195 HashCode:109601484
taskAffinity:com.mupceet.activitytaskdemo

解析:

結(jié)論 來(lái)源
Activity 啟動(dòng)到新的任務(wù)棧中,即使是默認(rèn)的 taskAffinity MainActivity 與 SingleInstanceActivity 的 TaskId 不相同
除了第一次啟動(dòng)時(shí)創(chuàng)建實(shí)例,其它多次啟動(dòng)復(fù)用并調(diào)到前臺(tái) SingleInstanceActivity 的 HashCode 相同,Intent 由 onNewIntent 處理
啟動(dòng)的 Activity 運(yùn)行在其他任務(wù)棧中 SingleInstanceActivity 與 MainActivity 的 TaskId 不相同,而且由于 MainActivity 是 standard 模式,啟動(dòng)時(shí)創(chuàng)建了新實(shí)例,棧中有兩個(gè) MainActivity 實(shí)例

測(cè)試 8:在測(cè)試 7 基礎(chǔ)上改為調(diào)用 SingleTopActivity

MainActivity--> SingleTopActivity--> SingleInstanceActivity--> SingleTopActivity--> SingleInstanceActivity

結(jié)果:

************* onCreate *************
MainActivity TaskId: 1196 HashCode:141418922
taskAffinity:com.mupceet.activitytaskdemo
************* onCreate *************
SingleTopActivity TaskId: 1196 HashCode:74869513
taskAffinity:com.mupceet.activitytaskdemo
************* onCreate *************
SingleInstanceActivity TaskId: 1197 HashCode:193894545
taskAffinity:com.mupceet.activitytaskdemo
************* onNewIntent *************
SingleTopActivity TaskId: 1196 HashCode:74869513
taskAffinity:com.mupceet.activitytaskdemo
************* onNewIntent *************
SingleInstanceActivity TaskId: 1197 HashCode:193894545
taskAffinity:com.mupceet.activitytaskdemo

解析:

結(jié)論 來(lái)源
Activity 啟動(dòng)到新的任務(wù)棧中,即使用默認(rèn)的 taskAffinity MainActivity 與 SingleInstanceActivity 的 TaskId 不相同
除了第一次啟動(dòng)時(shí)創(chuàng)建實(shí)例,其它多次啟動(dòng)復(fù)用并調(diào)到前臺(tái) SingleInstanceActivity 的 HashCode 相同,Intent 由 onNewIntent 處理
啟動(dòng)的 Activity 運(yùn)行在其他任務(wù)棧中 啟動(dòng)的 SingleTopActivity 的 HashCode 相同,因?yàn)?SingleTopActivity 是 singleTop 模式,啟動(dòng)時(shí)未創(chuàng)建新實(shí)例,Intent 由 onNewIntent 處理

測(cè)試 9:

MainActivity--> SingleInstanceActivity--> StandardActivity

結(jié)果:

************* onCreate *************
MainActivity TaskId: 1206 HashCode:241879363
taskAffinity:com.mupceet.activitytaskdemo
************* onCreate *************
SingleInstanceActivity TaskId: 1209 HashCode:213193939
taskAffinity:com.mupceet.activitytaskdemo
************* onCreate *************
StandardActivity TaskId: 1206 HashCode:213531793
taskAffinity:com.mupceet.activitytaskdemo

解析:

結(jié)論 來(lái)源
Activity 啟動(dòng)到新的任務(wù)棧中,即使用默認(rèn)的 taskAffinity MainActivity 與 SingleInstanceActivity 的 TaskId 不相同
啟動(dòng)的 Activity 運(yùn)行在其他任務(wù)棧中 SingleInstanceActivity 與 StandardActivity 的 TaskId 不相同,但由于 StandardActivity 和 MainActivity 的 taskAffinity 相同,它們存在于同一個(gè)任務(wù)棧中

測(cè)試 10:

(TaskDemo) MainActivity --> SingleInstanceActivity --> home 返回主頁(yè)
(TaskDemo2) MainActivity --> SingleInstanceActivity

結(jié)果:

************* onCreate *************
MainActivity TaskId: 1206 HashCode:241879363
taskAffinity:com.mupceet.activitytaskdemo
************* onCreate *************
SingleInstanceActivity TaskId: 1207 HashCode:64163597
taskAffinity:com.mupceet.activitytaskdemo


************* onCreate *************
MainActivity TaskId: 1208 HashCode:241879363
taskAffinity:com.mupceet.activitytaskdemo2
************* onNewIntent *************
SingleInstanceActivity TaskId: 1207 HashCode:64163597
taskAffinity:com.mupceet.activitytaskdemo

解析:

結(jié)論 來(lái)源
Activity 在系統(tǒng)中僅會(huì)存在一個(gè)實(shí)例 不同應(yīng)用啟動(dòng)的 SingleInstanceActivity 的 TaskId 相同,HashCode 相同

1.2. allowTaskReparenting

在這種屬性情況下,Activity 在其關(guān)聯(lián)的任務(wù)轉(zhuǎn)到前臺(tái)時(shí),將從原先被啟動(dòng)時(shí)推入的任務(wù)棧移動(dòng)到與其具有關(guān)聯(lián)的任務(wù)棧中。

測(cè)試 11:TaskDemo2 啟動(dòng) TaskDemo 的 StandardActivity

(TaskDemo2) MainActivity --> ToDemoStandard --> home 返回主頁(yè)
(TaskDemo) MainActivity(打開(kāi)應(yīng)用)

結(jié)果:

************* onCreate *************
MainActivity TaskId: 1220 HashCode:241879363
taskAffinity:com.mupceet.activitytaskdemo2
************* onCreate *************
StandardActivity TaskId: 1220 HashCode:241879363
taskAffinity:com.mupceet.activitytaskdemo

(打開(kāi) Demo 應(yīng)用無(wú)輸出)

打開(kāi) TaskDemo 前:

Running activities (most recent first):
  TaskRecord{f0c1e3 #1222 A=com.mupceet.activitytaskdemo2 U=0 StackId=1 sz=2}
    Run #1: ActivityRecord{a32ff5f u0 com.mupceet.activitytaskdemo/.StandardActivity t1222}
    Run #0: ActivityRecord{371f577 u0 com.mupceet.activitytaskdemo2/.MainActivity t1222}

打開(kāi) TaskDemo 后:

Running activities (most recent first):
  TaskRecord{18af934 #1223 A=com.mupceet.activitytaskdemo U=0 StackId=1 sz=2}
    Run #1: ActivityRecord{a32ff5f u0 com.mupceet.activitytaskdemo/.StandardActivity t1223}
  TaskRecord{f0c1e3 #1222 A=com.mupceet.activitytaskdemo2 U=0 StackId=1 sz=1}
    Run #0: ActivityRecord{371f577 u0 com.mupceet.activitytaskdemo2/.MainActivity t1222}

解析:

結(jié)論 來(lái)源
standard 模式的 Activity 被啟動(dòng)時(shí)將被推入啟動(dòng)的任務(wù)棧中 Demo2 的 MainActivity 與其啟動(dòng)的 Demo 的 StandardActivity 的 TaskId 相同
allowTaskReparenting 的 Activity 被其關(guān)聯(lián)的任務(wù)啟動(dòng)時(shí)將被轉(zhuǎn)移到關(guān)聯(lián)的任務(wù)棧中 Demo 啟動(dòng)的 StandardActivity 未重新實(shí)例化,而是在任務(wù)棧中移動(dòng)

2. 改變?nèi)蝿?wù)恢復(fù) Activity 時(shí)的默認(rèn)行為

如上文默認(rèn)行為所述,如果用戶長(zhǎng)時(shí)間離開(kāi)任務(wù),則系統(tǒng)會(huì)清除任務(wù)棧中除根 Activity 之外的所有 Activity。當(dāng)用戶再次返回到任務(wù)時(shí),僅恢復(fù)根 Activity。系統(tǒng)這樣做的原因是,經(jīng)過(guò)很長(zhǎng)一段時(shí)間后,用戶可能已經(jīng)放棄之前執(zhí)行的操作,返回到任務(wù)是要開(kāi)始執(zhí)行新的操作。要修改恢復(fù) Activity 任務(wù)棧的行為可以使用以下三個(gè)屬性。

2.1. alwaysRetainTaskState

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

2.2. clearTaskOnLaunch

如果在任務(wù)的根 Activity 中將此屬性設(shè)置為 "true",則每當(dāng)用戶離開(kāi)任務(wù)然后點(diǎn)擊圖標(biāo)返回時(shí),系統(tǒng)都會(huì)將堆棧清除到只剩下根 Activity。即使只離開(kāi)任務(wù)片刻時(shí)間,用戶也始終會(huì)返回到任務(wù)的初始狀態(tài)。

測(cè)試 12:點(diǎn)擊屬于 TaskDemo2 的 StandardActivity 圖標(biāo)

StandardActivity --> StandardActivity --> StandardActivity --> StandardActivity

結(jié)果:

************* onCreate *************
StandardActivity TaskId: 1229 HashCode:241879363
taskAffinity:com.mupceet.activitytaskdemo2
************* onCreate *************
StandardActivity TaskId: 1229 HashCode:235658412
taskAffinity:com.mupceet.activitytaskdemo2
************* onCreate *************
StandardActivity TaskId: 1229 HashCode:188962139
taskAffinity:com.mupceet.activitytaskdemo2
************* onCreate *************
StandardActivity TaskId: 1229 HashCode:34150381
taskAffinity:com.mupceet.activitytaskdemo2
Running activities (most recent first):
  TaskRecord{d2b8f13 #1229 A=com.mupceet.activitytaskdemo2 U=0 StackId=1 sz=4}
    Run #3: ActivityRecord{e71827f u0 com.mupceet.activitytaskdemo2/.StandardActivity t1229}
    Run #2: ActivityRecord{7a51fa1 u0 com.mupceet.activitytaskdemo2/.StandardActivity t1229}
    Run #1: ActivityRecord{ef87b33 u0 com.mupceet.activitytaskdemo2/.StandardActivity t1229}
    Run #0: ActivityRecord{638598e u0 com.mupceet.activitytaskdemo2/.StandardActivity t1229}

Home 回到主頁(yè)后,再次點(diǎn)擊桌面圖標(biāo)返回

Running activities (most recent first):
  TaskRecord{d2b8f13 #1229 A=com.mupceet.activitytaskdemo2 U=0 StackId=1 sz=1}
    Run #0: ActivityRecord{638598e u0 com.mupceet.activitytaskdemo2/.StandardActivity t1229}

可以看到任務(wù)棧中僅剩根 Activity 了,點(diǎn)擊一次 Back 即可退出。

2.3. finishOnTaskLaunch

該屬性與 clearTaskOnLaunch 類(lèi)似,但這個(gè)針對(duì)單個(gè) Activity 而不是整個(gè)任務(wù)。在任務(wù)轉(zhuǎn)入后臺(tái)再點(diǎn)擊桌面圖標(biāo)返回時(shí)設(shè)置該屬性為 "true" 的 Activity 將被銷(xiāo)毀。

參考資料:

最后編輯于
?著作權(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)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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