測試環(huán)境:Google Nexus 4- 5.0.0- API 21
工具: 使用adb shell dumpsys activity 查看activity 屬于哪個task
新建或重用activity的生命周期
啟動一個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 只允許單例存在且獨占一個task 里面
SingleTask
-如果已存在taskAffinity 一致的task,進(jìn)一步判斷是否存在改activity,存在則重用,并把這位置之上的清除,否則新建一個放在上面。
-如果不存在taskAffinity 一致的task,新建一個task
taskAffinity: task類型,用于區(qū)分task. task的taskAffinity等于第一個插入該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定義了一個新taskAffinity,所以放在一個新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ù)的時候是分開顯示的,如果從用戶的角度來看,一個 .apk 文件包含多個“應(yīng)用”,需要使用 taskAffinity 屬性將不同關(guān)聯(lián)分配給與每個“應(yīng)用”相關(guān)的 Activity。
taskAffinity 在兩種情況下生效:
- FLAG_ACTIVITY_NEW_TASK
singleTask,SingleInstance 也相當(dāng)于包含了這個flag
- android:allowTaskReparenting="true"
Activity 可以從其啟動的任務(wù)移動到與其具有關(guān)聯(lián)的任務(wù)(如果該任務(wù)出現(xiàn)在前臺)
示例:
應(yīng)用A啟動應(yīng)用B的Activity B( 設(shè)置allowTaskReparenting="true"),按home鍵退回桌面啟動應(yīng)用B,此時顯示的并不會是B的MainActivity,而是顯示Activity B
使用android:taskAffinity這個屬性時,如果指定的值不含.,會出現(xiàn)這樣的錯誤:
Failure [INSTALL_PARSE_FAILED_MANIFEST_MALFORMED]
可以考慮采用類似java包名的做法:比如com.xxx.xx
Intent Flag:
FLAG_ACTIVITY_SINGLE_TOP
與 "singleTop" launchMode 值相同的行為。FLAG_ACTIVITY_CLEAR_TOP
存在則重用并銷毀該位置之上的 Activity.
注:如果指定 Activity 的啟動模式為 "standard",則該 Activity 也會從堆棧中刪除,并在其位置啟動一個新實例FLAG_ACTIVITY_NEW_TASK
根據(jù)Affinity判斷是否需要創(chuàng)建新的Task,然后再創(chuàng)建新的Activity實例放進(jìn)去。(棧頂級別的重利用)FLAG_ACTIVITY_NO_HISTORY
如果設(shè)置,新的Activity將不再歷史stack中保留。用戶一離開它,這個Activity就關(guān)閉了。這也可以通過XML設(shè)置noHistory
注意: FLAG_ACTIVITY_NEW_TASK+FLAG_ACTIVITY_CLEAR_TOP 才等于singleTask.
清理返回棧
默認(rèn):如果用戶長時間離開任務(wù),則系統(tǒng)會清除所有 Activity 的任務(wù),根任務(wù)除外。 當(dāng)用戶再次返回到任務(wù)時,僅恢復(fù)根 Activity。
可以使用下列幾個 Activity 屬性修改此行為:
alwaysRetainTaskState
如果task根 Activity 中將此屬性設(shè)置為 "true",即使在很長一段時間后,所有 Activity 保留在其堆棧中。clearTaskOnLaunch
如果在task根 Activity 中將此屬性設(shè)置為 "true",則每當(dāng)用戶離開task然后返回時,系統(tǒng)都會將堆棧清除到只剩下根 Activity。finishOnTaskLaunch
類似于 clearTaskOnLaunch,但它對單個 Activity 起作用,而非整個任務(wù)。
startActivityForResult
Activity A startActivityForResult -> Activity B
在 Android 4.X 系統(tǒng)上,如果A 為singleTask,SingleInstance或者B為singleTask,SingleInstance則會在LaunchFlags中加入FLAG_ACTIVITY_NEW_TASK標(biāo)志,而含有FLAG_ACTIVITY_NEW_TASK標(biāo)志的話,onActivityResult將會立即接收到一個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.lxweimin.com/p/eceda0e4963e