Android啟動模式

HFW發表於2019-03-13

前言

昨天在複習總結Activity相關知識的時候,無意中看到了啟動模式,於是就想把啟動模式總結下。那麼啟動模式有什麼用?就是指定Activity該怎麼執行,比如決定新開的Activity執行在呼叫方的任務棧中還是執行於一個新的任務棧等等

一、四種啟動模式

下面所講述的啟動模式都是不加Intent的flag時的情形

1. standard(預設值)

該啟動模式的Activity可以位於所有任務棧,每次啟動都會新建立一個Activity例項,taskAffinity屬性對該模式無影響,新啟動的Activity始終與原有Activity同屬於一個棧(前提是原有Activity的啟動模式不是singleInstance)

  • 例一 當應用程式A的A1 Activity啟動應用程式B的B1(standard) Activity,B1會和A1同屬 於一個棧(前提是A1的啟動模式不是singleInstance)。
  • 例二 當應用程式A的A1(standard) Activity不停的啟動自己,那麼棧中A1例項就會越來越多

2. singleTop

棧頂複用模式,該啟動模式與standard的區別僅僅在於如果待啟動的Activity已經處於目標棧頂了那麼將不會再次建立例項,而只是呼叫該Activity的onNewIntent回撥(其實會先呼叫onPause然後才是onNewIntent最後onResume)

  • 例一 當應用程式A的A1(singleTop) Activity不停的啟動自己,棧中還是隻會有一個例項只是onNewIntent不斷的呼叫

3. singleTask

該啟動模式的Activity整個系統的所有任務棧最多隻能擁有一個例項,並且其啟動後所在的任務棧是固定的,固定為特定taskAffinity的任務棧,如果任務棧中已經擁有了一個該Activity的例項那麼不會再建立例項而是將該例項上面的所有Activity都關閉掉,然後呼叫該Activity的onNewIntent

  • 例一 當應用程式A的A1 Activity啟動應用程式B的B1(singTask) Activity,B1不和A1同屬於一個棧(特別的當A1與A2的taskAffinity一致時會執行在同一個棧中)
  • 例二 應用程式A有A1(singleTask)、A2兩個Activity,A1啟動A2,然後A2啟動A1,這時候會發現任務棧中只有A1了。

4. singleInstance

該啟動模式與singleTask的唯一區別就是其會執行在一個單獨的棧中,並且該棧中不允許其它Activity 進入

二、返回頁面問題

點選返回鍵,系統會關閉當前處於前臺的任務棧棧頂的Activity如果處於前臺的任務棧中的Activity都被關閉了就會將最近被切換到後臺的返回棧切換到前臺以此迴圈

  • 例一 應用程式A有A1、A2(singleTask)兩個Activity,應用程式B有B1一個Activity,A1啟動A2然後切換回後臺,啟動B1,B1再啟動A2,這時候點選返回鍵會返回哪個頁面?答案是A1,因為當B1啟動了A2時系統判定特定taskAffinity的任務棧中A2例項是否存在,如果存在就把包括A1、A2的任務棧整個切換回前臺,所以點選返回鍵出現的是A1

三、通過設定常用Flags啟動Activity

1. FLAG_ACTIVITY_NEW_TASK

該Flag有以下兩個作用

  1. 第一個作用是使非Activity的Context可以啟動Activity比如在Service裡面啟動一個Activity就得設定這個Flag
  2. 第二個作用是將啟動模式為standard、singleTop、singleTask的Activity執行在特定taskAffinity的任務棧中。注意當設定了該Flag以後呼叫startActivityForResult將會立即返回(啟動啟動模式為singleTask和singleInstance的Activity自帶該Flag)
  • 例一 在不考慮修改了taskAffinity的情況下,當應用程式A的A1(standard) Activity通過新增FLAG_ACTIVITY_NEW_TASK後啟動自己會發現新增了該Flag與沒加一樣,還是會每次建立一個A1的例項壓入棧,原因是新增了該Flag後系統會查詢待啟動的Activity也就是A1指定的taskAffinity棧是否存在,如不存在就建立該棧然後建立一個例項壓入棧,如果存在也會建立一個例項壓入棧。

    思考:如果在本例中A1的啟動模式為singleTop、singleTask、singInstance又會怎麼樣?首先對singleTask和singleInstance無影響因為它們預設就設定了該Flag,對於singleTop在本例中也相當於沒設定該Flag,點選啟動不會建立新的例項只是會呼叫onNewIntent

  • 例二 在不考慮修改了taskAffinity的情況下,當應用程式A的A1 Activity通過新增FLAG_ACTIVITY_NEW_TASK 啟動應用程式B的B1(standard) Activity,一共會有幾個任務棧?答案是2個,如果沒設定這個Flag那麼結果是1個,設定了以後系統發現B1指定的taskAffinity的棧還沒啟動就會啟動然後建立B1將其壓入棧

    思考:如果在本例中B1的啟動模式為singleTop、singleTask、singInstance又會怎麼樣?首先對singleTask和singleInstance無影響因為它們預設就設定了該Flag,對於singleTop而言任務棧也會變成兩個其原理與standard一致

2. FLAG_ACTIVITY_SINGLE_TOP

該Flag只對目標Activity啟動模式為standard的Activity起作用,使其產生的行為與singleTop一致

3. FLAG_ACTIVITY_CLEAR_TOP

對於啟動模式為standard的Activity來說,如果啟動時發現在目標棧中已經有該Activity的例項了,那麼會將該Activity及其上面的所有Activity全部銷燬,然後重建該Activity,對於啟動模式是singTop或者同時設定了FLAG_ACTIVITY_CLEAR_TOPFLAG_ACTIVITY_SINGLE_TOP來說會將上面的Activity銷燬然後回撥該Activity的onNewIntent(並不會把自己銷燬再重建)

四、啟動模式的應用場景

  • singleTop 比如一個App收到若干個通知每個通知都要開啟同一個頁面檢視資訊,這時候如果使用者看完一個再點選另一個就不會再開啟一個該介面而只會重新整理資料
  • singleTask 一般用於應用程式的首頁,比如瀏覽器首頁
  • singleInstance 應用於社交App的分享介面(微博、QQ、微信等),注意這裡有個問題,當A應用程式開啟分享頁面然後輸入了部分內容後然後切到後臺,開啟B應用程式再次開啟分享頁面,這樣由於分享頁面是singleInstance因此會被複用,那麼編輯過的內容也會被保留,如果不需要保留我們可以監聽onNewIntent,在該回撥方法中清除編輯過的內容

相關文章