启动模式 和 任务栈
1. LaunchMode
再簡單的東西也需要認真對待。
Activity的四中啟動模式:
首先是 standard ,這是系統默認的啟動模式。
當我們啟動新的Activity時候,是調用 Context 的startActivity() 方法。
但是,如果這個Context不是Activity類型而是ApplicationContext。那這時候會報錯,無法啟動。因為在standard模式下,是在當前Activity的所屬任務棧中啟動新的Activity,如果這個Context不是Activity類型的話,那么就不存在所謂的Activity任務棧了,報錯也就理所當然了。所以這個時候可以配置 Flag (FLAG_ACTIVITY_NEW_TASK),這時候實際上以singleTask模式啟動。在新的任務棧中啟動Activity。這樣,就可以使用ApplicationContext啟動Activity。?乛?乛?
再看singleTop,如果這個Activity已經存在于這個棧的棧頂,那么就會復用這個Activity,不會重新創建新的Activity。這個時候Activity 的onCreate() 和 onStart() 不會被調用。但是會有另一個方法 onNewIntent() 方法被調用。當配置了singleTop的Activity處于棧頂,又再次被啟動的時候,調用如下:
然后是singleTask 棧內復用。這種模式下,只要Activity在 某一個棧內(可能存在多個棧) 存在,就回復用這個Activity,而不會去重新創建。和singleTop一樣,系統也會調用 onNewIntent() 方法。
這里有幾種情況,首先是請求的棧是本棧還是一個新棧,還有就是Activity存不存在。
現在有個Activity棧,有ABC三個Activity。要創建一個新的Activity D。
1. 本Activity棧 — Activity不存在
這種情況最簡單,創建一個新的Activity,壓入棧中即可。這個棧變成了 ABCD。
2. 本Activity棧 — Activity存在
這是如果本棧的Activity 是 ADBC 這個樣子。然后再使用singleTask模式啟動 D 這個Activity。系統會將D 調到棧頂,并且調用D的 onNewIntent() 方法。同時會將D上面的所有Activity清除掉。這時棧變成了 AD。
3. 新Activity棧 — Activity不存在
這個時候需要重新創建因為這個棧不存在,這個Activity也存在,所以這時,系統先創建一個棧,然后再創建一個Activity,再將Activity壓入新棧中。
4. 新Activity棧 — Activity存在
這是最復雜一種情況。這時候會有一個 后臺棧 和 前臺棧 的概念。
先來分析這種情況,當前Activity肯定處于前臺棧,既然新的Activity要在新的棧中啟動,并且Activity已經存在,那么,這個棧肯定已經創建完成,并且屬于 后臺棧 。這時,系統會先將整個任務棧調到前臺,然后再按照singleTask 原則,該復用復用,該清除清除。這時整個棧中的所有Activity都會被調到另一個棧之前。所以,一直按Back鍵,回退的Activity順序會有所改變。
最后是 singleInstance 。一種加強型的singleTask。擁有singleTask的所有特性。不同在于,這個模式的Activity會在一個新的獨特的棧中創建Activity,這個棧中只有這個Activity存在。由于棧內復用的特性,所有的這個Activity啟動時都不會重新創建。除非這個獨特的任務棧被系統殺死。
2. 任務棧
這里主要說明兩個配置參數 taskAffinity 和 allowTaskReparenting 。
taskAffinity:每個Activity都有 taskAffinity 屬性,這個屬性指出了它希望進入的Task。默認情況下,taskAffinity 的值是包名。所以如果你設置了這個屬性是包名的話,那和沒設置是一樣的。
<activity android:name=".Act3" android:taskAffinity="com.mytest.task2"/>如果想要Activity在新的任務棧中啟動,那么需要兩步:
在Activity中可以使用 Activity. getTaskId() 方法來獲取當前Task的 ID。驗證自己的猜想。
allowTaskReparenting :這個屬性用于設定Activity能夠從啟動它的任務中轉移到另一個與啟動它的任務有親緣關系的任務中。
這個親緣關系只能和根Activity去比較,所以必須在根Activity設置taskAffinity,而需要轉移的Activity不需要是根Activity。
如果設置了true,則能夠轉移,如果設置了false,則這個Activity保留在啟動它的那個任務中。
設置方式:
這里比較難理解,舉個例子吧:
現在有兩個應用 應用A、 應用B 。
應用A 是在前臺的應用,應用B是后臺應用。
應用B 的 Act 1 和 Act 2 有相同的taskAffinity。(這樣就具有了親緣關系)
應用B 的 Act 2 配置了android:allowTaskReparenting="true" 。
現在 應用A 啟動應用B 的 Act 2。
然后回到桌面,啟動應用B 的 Act 1。
流程如下:
其中,Act 2 這個Activity從應用A的棧中,轉移到了應用B的棧的頂端。
(可以將應用B 的 Act 2想象成瀏覽器的網頁界面。其他應用打開了網頁。這時打開瀏覽器應用,那個打開的網頁處于最前端)
總結
以上是生活随笔為你收集整理的启动模式 和 任务栈的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: include、ViewStub、mer
- 下一篇: ios 中的基本算数函数