Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android-啟動模式task-lunchmodle-intent flag 總結

Android-啟動模式task-lunchmodle-intent flag 總結

編輯:關於Android編程

 

總結:

  • 同一task內的activity可以是來自不同進程的activity
  • 棧內的activity不會重新排序,只能push或者pop
  • standard模式允許多實例,可以在不同的task
  • singleTask的activity只會存在一個實例
  • singleTask的activity如果設置了獨立的taskAffinity屬性值,啟動時就會在新的task中,否則會在已有task中
  • singleTask的activity啟動時,它會在目標task(新的task或者已有task)中查看是否已經存在相應的activity實例,如果存在,就會把位於這個activity實例上面的activity全部銷毀(pop, destroy)掉,即最終這個activity實例會位於任務的堆棧頂端中

    task

    task是一個從用戶角度出發的概念,它是一些activity的組合,它們組合起來是為了讓用戶完成某一件工作(或者說操作)。

    task內的activity們以棧的形式組織起來,也就是back stack了。棧內的activity不會重新排序,只能push或者pop。棧內的activity可以來自不同的app,因此可以是運行在不同的進程,但是它們都屬於同一個task內。

    安卓系統是實時多task系統,用戶可以隨意在多個task之間切換。當一個task的棧內所有activity都pop之後,task也就銷毀了。有時系統為了回收內存,會銷毀activity,但是task不會銷毀。

    activity在manifest中有launchMode選項,可以配置其啟動的模式。標准模式下,允許一個activity同時存在多個實例,既可以在同一個task,也可以在不同task。manifest可以指定launchMode,intent可以指定intent flag,前者供被啟動者使用,後者供啟動者使用,同時使用時後者會覆蓋前者。

    launchMode

    • standard,默認模式,允許多實例
    • singleTop,相比於standard,有新的啟動請求時,只有在目標activity處於當前棧頂時,才會調用onNewIntent()而不創建新實例,其他情況都和standard一致
    • singleTask,(這段摘自老羅的博客)設置了”singleTask”啟動模式的Activity,它在啟動的時候,會先在系統中查找屬性值affinity等於它的屬性值taskAffinity的任務存在;如果存在這樣的任務,它就會在這個任務中啟動,否則就會在新任務中啟動。因此,如果我們想要設置了”singleTask”啟動模式的Activity在新的任務中啟動,就要為它設置一個獨立的taskAffinity屬性值。如果設置了”singleTask”啟動模式的Activity不是在新的任務中啟動時,它會在已有的任務中查看是否已經存在相應的Activity實例,如果存在,就會把位於這個Activity實例上面的Activity全部結束掉,即最終這個Activity實例會位於任務的堆棧頂端中。
    • singleInstance,和singleTask相比,不同點在於singleInstance activity所在的task只會有這一個activity
    • 返回導航:singleTask和singleInstance啟動的activity,盡管可能不在同一個task,但是仍然會回到原來的activity;但是singleTask可能會存在back stack“拼接”的情況

      launchMode驗證測試

      主要測試的是singleTask這一屬性,其他的文檔描述都比較清楚,也不容易產生誤解。兩組實驗,不設置taskAffinity和設置taskAffinity時,singleTask的行為。對比兩者“最近任務”,dumpsys,logcat,返回導航的差異。

      測試1

      不設置taskAffinity,MainActivity -> SingleTaskFirstActivity -> SimpleActivity -> SingleTaskSecondActivity -> 選擇圖片Intent,再一路返回。

      最近任務內只能看到一個TaskDemo的任務,dumpsys的結果如下:

      dumpsys的結果

      所有的activity均在同一個task內,驗證了老羅的結論。另外注意標紅的兩處,它們的ProcessRecord對象不同,ImageGallery和SingleTaskActivity處於不同的進程,也驗證了前文所述“可以運行在不同的進程”。

      logcat日志如下:

      logcat的結果

      一路返回依次回到SingleTaskSecondActivity, SimpleActivity, SingleTaskFirstActivity,MainActivity, 桌面。

      測試2

      設置SingleTaskFirstActivity的taskAffinity為單獨的值,MainActivity -> SingleTaskFirstActivity。

      通過最近任務可以看到,有了兩個TaskDemo的任務。而dumpsys結果如下:

      dumpsys的結果2

      可以看到,MainActivity和SingleTaskFirstActivity運行在了兩個不同的task裡面(棧底為MainActivity的t225, 棧底為SingleTaskFirstActivity的t226),但是他們仍屬於同一進程。

      我們接著啟動SimpleActivity,再通過最近任務切換回t225,並且也啟動SimpleActivity,這時通過dumpsys結果如下:

      dumpsys的結果3

      SimpleActivity同時存在兩個實例,他們的hashCode是不同的,目前處於resumed狀態的是在t225中的實例。

      而通過查看logcat:

      logcat的結果2

      我們同樣發現SimpleActivity被創建了兩個實例。

      此時我們通過最近任務切換回t226,並在此啟動SingleTaskSecondActivity,查看dumpsys,然後再切換回t225也啟動SingleTaskSecondActivity,查看dumpsys和logcat:

      dumpsys的結果4dumpsys的結果5logcat的結果3

      我們可以看到盡管第一次啟動SingleTaskSecondActivity是在t226,但是SingleTaskSecondActivity實例卻運行在t225中,為什麼呢?因為SingleTaskSecondActivity並沒有設置taskAffinity屬性,所以它和MainActivity將會運行在同一個task中!和老羅的分析一致。而第二次啟動時,並未創建新的SingleTaskSecondActivity實例,而是調用了它的onNewIntent方法,和文檔描述一致。

      現在我們測試一下返回導航,依次按下返回鍵,觀察每次回到的activity,以及每次dumpsys的結果,以及logcat的結果:

      第一次回到了t225的SimpleActivity,dumpsys:第1次dumpsys的結果

      第二次回到了t225的MainActivity,dumpsys:第2次dumpsys的結果

      第三次回到了t226的SimpleActivity,dumpsys:第3次dumpsys的結果

      第四次回到了t226的SingleTaskFirstActivity,dumpsys:第4次dumpsys的結果

      最後一次返回就回到了桌面。

      logcat日志如下:依次返回logcat的結果

      從上面的返回路徑來看,確實驗證了developer文檔上關於back stack“拼接”的情況的描述,即:並不是按照most recent first的順序返回的,而是優先把一個task的back stack(t225) pop完畢之後,再pop下一個task的back stack(t226)。

      測試3

      基於測試2的版本,MainActivity -> SingleTaskFirstActivity -> SimpleActivity,再切換回MainActivity,再啟動SingleTaskFirstActivity。

      查看最近任務,仍然有兩個task,但是查看dumpsys以及logcat:測試3 dumpsys的結果測試3 logcat的結果

      我們可以看到,第一次啟動的SimpleActivity就被pop(destroy)了,從而把未在棧頂的SingleTaskFirstActivity提到了棧頂。這也驗證了back stack內的activity不會重新排序,最會pop和push的事實。

      Intent flag

      只要搞清楚了launchMode中容易產生誤解的地方,對於intent flag來說,只需要記住一點即可:intent flag可以覆蓋launchMode的設置。為了避免內容過於冗長,本文就不對intent flag進行詳細的測試分析了。

      總結

      • 同一task內的activity可以是來自不同進程的activity
      • 棧內的activity不會重新排序,只能push或者pop
      • standard模式允許多實例,可以在不同的task
      • singleTask的activity只會存在一個實例
      • singleTask的activity如果設置了獨立的taskAffinity屬性值,啟動時就會在新的task中,否則會在已有task中
      • singleTask的activity啟動時,它會在目標task(新的task或者已有task)中查看是否已經存在相應的activity實例,如果存在,就會把位於這個activity實例上面的activity全部銷毀(pop, destroy)掉,即最終這個activity實例會位於任務的堆棧頂端中
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved