Task
官方文檔 ?中關于task的解釋:
任務是指在執行特定作業時與用戶交互的一系列 Activity。 這些 Activity 按照各自的打開順序排列在堆棧(即返回棧)中。
task是可以跨應用的,這正是task存在的一個重要原因。有的Activity,雖然不在同一個app中,但為了保持用戶操作的連貫性,把他們放在同一個任務中。例如,在我們的應用中的一個Activity A中點擊發送郵件,會啟動郵件程序的一個Activity B來發送郵件,這兩個activity是存在于不同app中的,但是被系統放在一個任務中,這樣當發送完郵件后,用戶按back鍵返回,可以返回到原來的Activity A中,這樣就確保了用戶體驗。
Lunch mode
1.android:launchMode
"standard"(默認模式)
默認。系統在啟動 Activity 的任務中創建 Activity 的新實例并向其傳送 Intent。Activity 可以多次實例化,而每個實例均可屬于不同的任務,并且一個任務可以擁有多個實例
在這種模式下啟動的activity可以被多次實例化,即在同一個任務中可以存在多個activity的實例,每個實例都會處理一個Intent對象。如果Activity A的啟動模式為standard,并且A已經啟動,在A中再次啟動Activity A,即調用startActivity(new Intent(this,A.class)),會在A的上面再次啟動一個A的實例,即當前的桟中的狀態為A-->A。
"singleTop"
如果當前任務的頂部已存在 Activity 的一個實例,則系統會通過調用該實例的onNewIntent()方法向其傳送 Intent,而不是創建 Activity 的新實例。Activity 可以多次實例化,而每個實例均可屬于不同的任務,并且一個任務可以擁有多個實例(但前提是位于返回棧頂部的 Activity 并不是 Activity 的現有實例)。
如果A的啟動模式為singleTop,并且A的一個實例已經存在于棧頂中,再次啟動A時,不會再次創建A的實例,而是重用原來的實例,并且調用原來實例的onNewIntent()方法。任務桟中還是這有一個A的實例。
如果以singleTop模式啟動的activity的一個實例已經存在與任務桟中,但是不在桟頂,那么它的行為和standard模式相同,也會創建多個實例。
"singleTask"
系統創建新任務并實例化位于新任務底部的 Activity。但是,如果該 Activity 的一個實例已存在于一個單獨的任務中,則系統會通過調用現有實例的onNewIntent()方法向其傳送 Intent,而不是創建新實例。一次只能存在 Activity 的一個實例。
在同一個任務中具有唯一性,至于會不會開啟新的任務與taskAffinity有關。
taskAffinity: Activity 有著親和關系的任務。從概念上講,具有相同親和關系的 Activity 歸屬同一任務(從用戶的角度來看,則是歸屬同一“應用”)。 任務的親和關系由其根 Activity 的親和關系確定。
如果沒有對activity設置該屬性的話,默認為application的*taskAffinity*,如果application也沒有設置,則為app的包名。
啟動一個singleTask模式的activity,會首先在系統中找與它的taskAffinity屬性一致的任務棧
????1.沒有特別指定taskAffinity,則為當前的task
? ? 2.如果指定了taskAffinity,先在系統中查找task,如果找不到則創建一個新的task,將activity作為root放置其中。
????3.如果要啟動的Activity已經存在、但沒有位于Task棧頂,系統會將把位于該Activity上面所有Activity移出Task,從而使其轉入棧頂。在該Activity之下的不變。
????a1->a2->a3->a1, a1 按back,直接退出,不會回到a3.
????4.如果需要在新的任務棧中啟動,就需要為activity設置獨立的taskAffinity.
? ? 5.如果當前activity是在新的任務棧中打開的話,那么之后在該activity中通過默認方式啟動的activity都在這個新的任務棧。
"singleInstance"
與?"singleTask"?相同,只是系統不會將任何其他 Activity 啟動到包含實例的任務中。該 Activity 始終是其任務唯一僅有的成員;由此 Activity 啟動的任何 Activity 均在單獨的任務中打開。
????1.具有全局唯一性,即整個系統中只會存在一個這樣的實例
? ? 2.具有獨占性,即它會獨自占用一個任務,被他開啟的任何activity都會運行在其他任務中。
? ? 3.被singleInstance模式的Activity開啟的其他activity,能夠開啟一個新任務,但不一定開啟新的任務,也可能在已有的一個任務中開啟(根據taskAffinity)。
2.Intent flag
啟動 Activity 時,您可以通過在傳遞給startActivity()的 Intent 中加入相應的標志,修改 Activity 與其任務的默認關聯方式。可用于修改默認行為的標志包括:
在新任務中啟動 Activity。如果已為正在啟動的 Activity 運行任務,則該任務會轉到前臺并恢復其最后狀態,同時 Activity 會在onNewIntent()中收到新 Intent
類似singleTask。
如果正在啟動的 Activity 是當前 Activity(位于返回棧的頂部),則 現有實例會接收對onNewIntent()的調用,而不是創建 Activity 的新實例。
相當于launchMode中的singleTop,比如說原來棧中情況是A,B,C,D,在D中啟動D(加入該flag),棧中的情況還是A,B,C,D
如果正在啟動的 Activity 已在當前任務中運行,則會銷毀當前任務頂部的所有 Activity,并通過onNewIntent()將此 Intent 傳遞給 Activity 已恢復的實例(現在位于頂部),而不是啟動該 Activity 的新實例。
假設有A,B兩個Activity,在AndroidManifest.xml中將A Activity的設置了android:clearTaskOnLaunch="true"。然后A中的操作啟動了B,進入了B:(1)如果此時用戶按了Home鍵回到主屏幕上,然后又點擊了主屏幕上的A的icon圖標啟動應用。那么此時不是進入B,而是進入了A。(2)如果用戶按了屏幕下方的”最近任務列表“鍵,調出最近任務列表中,出現的是B,用戶點擊,此時又進入的是B。
參考
Android中Activity四種啟動模式和taskAffinity屬性詳解
Activity的任務棧Task以及啟動模式與Intent的Flag詳解
https://developer.android.com/guide/components/tasks-and-back-stack.html