測(cè)試環(huán)境:Google Nexus 4- 5.0.0- API 21
工具: 使用adb shell dumpsys activity 查看activity 屬于哪個(gè)task
新建或重用activity的生命周期
啟動(dòng)一個(gè)Activity根據(jù)launchMode 和Intent flag判斷是新建還是重用:
新建 : onCreate -> onStart -> onResume; 重用: onNewIntent ->(onStart)-> onResume.
getIntent() 得到的是原來的intent择同, 可以通過setIntent(Intent) 更新intent
launchMode
Standard
默認(rèn)模式近忙,新建并放在調(diào)用者的task里面
SingleTop
task頂一致則重用螺垢,否則新建
SingleInstance
該activity 只允許單例存在且獨(dú)占一個(gè)task 里面
SingleTask
-如果已存在taskAffinity 一致的task,進(jìn)一步判斷是否存在改activity贼穆,存在則重用,并把這位置之上的清除,否則新建一個(gè)放在上面茁肠。
-如果不存在taskAffinity 一致的task泽腮,新建一個(gè)task
taskAffinity: task類型,用于區(qū)分task. task的taskAffinity等于第一個(gè)插入該task的activity的taskAffinity,后面插入的activity的taskAffinity可以和stack的taskAffinity不同.
示例:
1.(A -> B -> C )
<Activity android:name=".A"/>
<Activity android:name=".B" android:launchMode="singleTask"/>
<Activity android:name=".C"/>
結(jié)果:
task1 | task2 |
---|---|
A B C |
B默認(rèn)taskAffinity與A相同都是包名御蒲,所以放在相同task里面;并且還未存在 所以新建B
2.(A -> B -> C)
<Activity android:name=".A"/>
<Activity android:name=".B" android:launchMode="singleTask" android:taskAffinity=".task2"/>
<Activity android:name=".C"/>
結(jié)果:
task1 | task2 |
---|---|
A | B C |
B定義了一個(gè)新taskAffinity,所以放在一個(gè)新task里面,C是默認(rèn)的诊赊,跟著創(chuàng)建它的B
3.(A -> B -> C -> B)
<Activity android:name=".A"/>
<Activity android:name=".B" android:launchMode="singleTask" android:taskAffinity=".task2"/>
<Activity android:name=".C"/>
結(jié)果:
task1 | task2 |
---|---|
A | B |
前面步驟和上面一樣厚满,最后轉(zhuǎn)到B需要清空B之上的activity
注意:
不同的taskAffinity 在長按home恢復(fù)的時(shí)候是分開顯示的,如果從用戶的角度來看,一個(gè) .apk 文件包含多個(gè)“應(yīng)用”豪筝,需要使用 taskAffinity 屬性將不同關(guān)聯(lián)分配給與每個(gè)“應(yīng)用”相關(guān)的 Activity痰滋。
taskAffinity 在兩種情況下生效:
- FLAG_ACTIVITY_NEW_TASK
singleTask,SingleInstance 也相當(dāng)于包含了這個(gè)flag
- android:allowTaskReparenting="true"
Activity 可以從其啟動(dòng)的任務(wù)移動(dòng)到與其具有關(guān)聯(lián)的任務(wù)(如果該任務(wù)出現(xiàn)在前臺(tái))
示例:
應(yīng)用A啟動(dòng)應(yīng)用B的Activity B( 設(shè)置allowTaskReparenting="true"),按home鍵退回桌面啟動(dòng)應(yīng)用B续崖,此時(shí)顯示的并不會(huì)是B的MainActivity敲街,而是顯示Activity B
使用android:taskAffinity這個(gè)屬性時(shí),如果指定的值不含.严望,會(huì)出現(xiàn)這樣的錯(cuò)誤:
Failure [INSTALL_PARSE_FAILED_MANIFEST_MALFORMED]
可以考慮采用類似java包名的做法:比如com.xxx.xx
Intent Flag:
FLAG_ACTIVITY_SINGLE_TOP
與 "singleTop" launchMode 值相同的行為多艇。FLAG_ACTIVITY_CLEAR_TOP
存在則重用并銷毀該位置之上的 Activity.
注:如果指定 Activity 的啟動(dòng)模式為 "standard",則該 Activity 也會(huì)從堆棧中刪除像吻,并在其位置啟動(dòng)一個(gè)新實(shí)例FLAG_ACTIVITY_NEW_TASK
根據(jù)Affinity判斷是否需要?jiǎng)?chuàng)建新的Task峻黍,然后再創(chuàng)建新的Activity實(shí)例放進(jìn)去复隆。(棧頂級(jí)別的重利用)FLAG_ACTIVITY_NO_HISTORY
如果設(shè)置,新的Activity將不再歷史stack中保留姆涩。用戶一離開它挽拂,這個(gè)Activity就關(guān)閉了。這也可以通過XML設(shè)置noHistory
注意: FLAG_ACTIVITY_NEW_TASK+FLAG_ACTIVITY_CLEAR_TOP 才等于singleTask.
清理返回棧
默認(rèn):如果用戶長時(shí)間離開任務(wù)骨饿,則系統(tǒng)會(huì)清除所有 Activity 的任務(wù)亏栈,根任務(wù)除外。 當(dāng)用戶再次返回到任務(wù)時(shí)宏赘,僅恢復(fù)根 Activity绒北。
可以使用下列幾個(gè) Activity 屬性修改此行為:
alwaysRetainTaskState
如果task根 Activity 中將此屬性設(shè)置為 "true",即使在很長一段時(shí)間后察署,所有 Activity 保留在其堆棧中闷游。clearTaskOnLaunch
如果在task根 Activity 中將此屬性設(shè)置為 "true",則每當(dāng)用戶離開task然后返回時(shí)贴汪,系統(tǒng)都會(huì)將堆棧清除到只剩下根 Activity脐往。finishOnTaskLaunch
類似于 clearTaskOnLaunch,但它對(duì)單個(gè) Activity 起作用嘶是,而非整個(gè)任務(wù)钙勃。
startActivityForResult
Activity A startActivityForResult -> Activity B
在 Android 4.X 系統(tǒng)上,如果A 為singleTask,SingleInstance或者B為singleTask,SingleInstance則會(huì)在LaunchFlags中加入FLAG_ACTIVITY_NEW_TASK標(biāo)志聂喇,而含有FLAG_ACTIVITY_NEW_TASK標(biāo)志的話辖源,onActivityResult將會(huì)立即接收到一個(gè)cancel的結(jié)果(android 5.0+ 可以正常返回了)
參考:
https://developer.android.com/guide/components/tasks-and-back-stack.html
http://www.cnblogs.com/lwbqqyumidi/p/3775479.html
http://www.reibang.com/p/eceda0e4963e