[TOC]html
在Android中Activity的啓動模式是能夠本身定義的,能夠經過兩種方法進行自定義:java
在使用清單定義時,能夠定義四種啓動模式以下: standard(默認模式)、singleTop、singleTask、singleInstance 使用例子以下:android
<activity android:name=".standard.StandardActivity" android:launchMode="standard"/>
複製代碼
若是沒有設置==android:launchMode== 默認爲standard(默認模式)模式。git
這個模式是默認模式,系統在啓動這個模式的Activity的任務中每次都會建立一個新的實例並向其傳送Intent。Activity能夠屢次實例化,並且每一個實例都可屬於不一樣的任務,而且一個任務能夠擁有多個實例。 以下圖所示:github
StandardActivity1 :onCreate 方法-------------------------
StandardActivity1 :onCreate:StandardActivity TaskId:143 TaskNum:2 hasCode:156403808
StandardActivity1:TaskAffinity:com.hugo.reviewbasic
StandardActivity1 :onStart 方法-------------------------
StandardActivity1 :onResume 方法-------------------------
MainActivity :onSaveInstanceState 方法-------------------------
MainActivity :onStop 方法-------------------------
StandardActivity1 :onPause 方法-------------------------
StandardActivity2 :onCreate 方法-------------------------
StandardActivity2 :onCreate:StandardActivity TaskId:143 TaskNum:3 hasCode:15174462
StandardActivity2:TaskAffinity:com.hugo.reviewbasic
StandardActivity2 :onStart 方法-------------------------
StandardActivity2 :onResume 方法-------------------------
StandardActivity1 :onSaveInstanceState 方法-------------------------
StandardActivity1 :onStop 方法-------------------------
StandardActivity2 :onPause 方法-------------------------
StandardActivity1 :onRestart 方法-------------------------
StandardActivity1 :onStart 方法-------------------------
StandardActivity1 :onResume 方法-------------------------
StandardActivity2 :onStop 方法-------------------------
StandardActivity2 :onDestroy 方法-------------------------
StandardActivity1 :onPause 方法-------------------------
MainActivity :onRestart 方法-------------------------
MainActivity :onStart 方法-------------------------
MainActivity :onResume 方法-------------------------
StandardActivity1 :onStop 方法-------------------------
StandardActivity1 :onDestroy 方法-------------------------
複製代碼
這裏咱們能夠看到standard啓動模式爲:每次啓動一個Activity都會從新建立一個新的實例。bash
這個模式是在當前堆棧的頂部已經存在Activity的一個實例了,則系統在啓動這個activity時,系統不會從新去建立一個新的實例,而是直接調用堆棧頂部的onNewIntent()返回向其傳送Intent。 在這個模式下 Activity能夠屢次實例化,並且每一個實例都可以屬於不一樣的任務棧,而且一個任務棧均可以擁有多個實例(可是前提是位於棧頂的Activity並非該Activity的現有實例)。app
以下圖所示:測試
下面是日誌:this
MainActivity :onPause 方法-------------------------
SingleTopActivity :onCreate 方法-------------------------
SingleTopActivity :onCreate:SingleTopActivity TaskId:145 TaskNum:2 hasCode:156403808
SingleTopActivity:TaskAffinity:com.hugo.reviewbasic
SingleTopActivity :onStart 方法-------------------------
SingleTopActivity :onResume 方法-------------------------
MainActivity :onSaveInstanceState 方法-------------------------
MainActivity :onStop 方法-------------------------
SingleTopActivity :onPause 方法-------------------------
SingleTopActivity :onNewIntent 方法-------------------------
SingleTopActivity :onNewIntent:SingleTopActivity TaskId:145 TaskNum:2 hasCode:156403808
SingleTopActivity:TaskAffinity:com.hugo.reviewbasic
SingleTopActivity :onResume 方法-------------------------
SingleTopActivity :onPause 方法-------------------------
OtherTopActiivty :onCreate 方法-------------------------
OtherTopActiivty :onCreate:OtherTopActiivty TaskId:145 TaskNum:3 hasCode:135228666
OtherTopActiivty:TaskAffinity:com.hugo.reviewbasic
OtherTopActiivty :onStart 方法-------------------------
OtherTopActiivty :onResume 方法-------------------------
SingleTopActivity :onSaveInstanceState 方法-------------------------
SingleTopActivity :onStop 方法-------------------------
OtherTopActiivty :onPause 方法-------------------------
SingleTopActivity :onCreate 方法-------------------------
SingleTopActivity :onCreate:SingleTopActivity TaskId:145 TaskNum:4 hasCode:204001128
SingleTopActivity:TaskAffinity:com.hugo.reviewbasic
SingleTopActivity :onStart 方法-------------------------
SingleTopActivity :onResume 方法-------------------------
OtherTopActiivty :onSaveInstanceState 方法-------------------------
OtherTopActiivty :onStop 方法-------------------------
SingleTopActivity :onPause 方法-------------------------
OtherTopActiivty :onRestart 方法-------------------------
OtherTopActiivty :onStart 方法-------------------------
OtherTopActiivty :onResume 方法-------------------------
SingleTopActivity :onStop 方法-------------------------
SingleTopActivity :onDestroy 方法-------------------------
OtherTopActiivty :onPause 方法-------------------------
SingleTopActivity :onRestart 方法-------------------------
SingleTopActivity :onStart 方法-------------------------
SingleTopActivity :onResume 方法-------------------------
OtherTopActiivty :onStop 方法-------------------------
OtherTopActiivty :onDestroy 方法-------------------------
SingleTopActivity :onPause 方法-------------------------
MainActivity :onRestart 方法-------------------------
MainActivity :onStart 方法-------------------------
MainActivity :onResume 方法-------------------------
SingleTopActivity :onStop 方法-------------------------
SingleTopActivity :onDestroy 方法-------------------------
複製代碼
咱們能夠看到在SingleTop模式下spa
在這個模式下啓動Activity時,若是棧中存在這個Activity的實例就會複用這個實例,無論它是否位於任務棧頂,複用時,會將它之上的全部其餘Activity的實例移動任務棧,而且調用該實例的onNewIntent()方法傳入Intent。其實在這個過程當中還存在一個任務棧的匹配,由於這個模式啓動時,會在本身須要的任務棧中尋找實例,這個任務棧是經過taskAffinity屬性指定的,若是任務棧不存在,則會建立這個任務棧。
任務棧在Androidmanifest 文件聲明Activity是設置 若是沒有設置默認爲軟件包名
任務棧設置以下:
<activity android:name=".singleTask.OtherSingleTaskActivity" android:launchMode="singleTask" android:taskAffinity="com.hugo.OtherSingleTaskActivity" />
複製代碼
例子步驟以下圖:
以上步驟日誌以下:
MainActivity :onPause 方法-------------------- hasCode:26596009
SingleTaskActivity :onCreate 方法-------------------------
SingleTaskActivity :onCreate:SingleTaskActivity hasCode:236910323 TaskId:166 TaskNum:2 TaskAffinity:com.hugo.reviewbasic
SingleTaskActivity :onStart 方法------------------ hasCode:236910323
SingleTaskActivity :onResume 方法-------------------- hasCode:236910323
MainActivity :onSaveInstanceState 方法------------------ hasCode:26596009
MainActivity :onStop 方法------------------- hasCode:26596009
SingleTaskActivity :onPause 方法-------------------- hasCode:236910323
OtherActivity :onCreate 方法-------------------------
OtherActivity :onCreate:OtherActivity hasCode:162823661 TaskId:166 TaskNum:3 TaskAffinity:com.hugo.reviewbasic
OtherActivity :onStart 方法------------------ hasCode:162823661
OtherActivity :onResume 方法-------------------- hasCode:162823661
SingleTaskActivity :onSaveInstanceState 方法------------------ hasCode:236910323
SingleTaskActivity :onStop 方法------------------- hasCode:236910323
OtherActivity :onPause 方法-------------------- hasCode:162823661
OtherSingleTaskActivity :onCreate 方法-------------------------
OtherSingleTaskActivity :onCreate:OtherSingleTaskActivity hasCode:182738289 TaskId:167 TaskNum:1 TaskAffinity:com.hugo.OtherSingleTaskActivity
OtherSingleTaskActivity :onStart 方法------------------ hasCode:182738289
OtherSingleTaskActivity :onResume 方法-------------------- hasCode:182738289
OtherActivity :onSaveInstanceState 方法------------------ hasCode:162823661
OtherActivity :onStop 方法------------------- hasCode:162823661
OtherSingleTaskActivity :onPause 方法-------------------- hasCode:182738289
OtherActivity :onCreate 方法-------------------------
OtherActivity :onCreate:OtherActivity hasCode:123068584 TaskId:167 TaskNum:2 TaskAffinity:com.hugo.reviewbasic
OtherActivity :onStart 方法------------------ hasCode:123068584
OtherActivity :onResume 方法-------------------- hasCode:123068584
OtherSingleTaskActivity :onSaveInstanceState 方法------------------ hasCode:182738289
OtherSingleTaskActivity :onStop 方法------------------- hasCode:182738289
OtherActivity :onDestroy 方法------------------- hasCode:162823661
OtherActivity :onPause 方法-------------------- hasCode:123068584
SingleTaskActivity :onNewIntent 方法-------------------- hasCode:236910323
SingleTaskActivity :onNewIntent:SingleTaskActivity hasCode:236910323 TaskId:166 TaskNum:2 TaskAffinity:com.hugo.reviewbasic
SingleTaskActivity :onRestart 方法------------------- hasCode:236910323
SingleTaskActivity :onStart 方法------------------ hasCode:236910323
SingleTaskActivity :onResume 方法-------------------- hasCode:236910323
OtherActivity :onSaveInstanceState 方法------------------ hasCode:123068584
OtherActivity :onStop 方法------------------- hasCode:123068584
SingleTaskActivity :onPause 方法-------------------- hasCode:236910323
MainActivity :onRestart 方法------------------- hasCode:26596009
MainActivity :onStart 方法------------------ hasCode:26596009
MainActivity :onResume 方法-------------------- hasCode:26596009
SingleTaskActivity :onStop 方法------------------- hasCode:236910323
SingleTaskActivity :onDestroy 方法------------------- hasCode:236910323
MainActivity :onPause 方法-------------------- hasCode:26596009
OtherActivity :onRestart 方法------------------- hasCode:123068584
OtherActivity :onStart 方法------------------ hasCode:123068584
OtherActivity :onResume 方法-------------------- hasCode:123068584
MainActivity :onStop 方法------------------- hasCode:26596009
MainActivity :onDestroy 方法------------------- hasCode:26596009
OtherActivity :onPause 方法-------------------- hasCode:123068584
OtherSingleTaskActivity :onRestart 方法------------------- hasCode:182738289
OtherSingleTaskActivity :onStart 方法------------------ hasCode:182738289
OtherSingleTaskActivity :onResume 方法-------------------- hasCode:182738289
OtherActivity :onStop 方法------------------- hasCode:123068584
OtherActivity :onDestroy 方法------------------- hasCode:123068584
OtherSingleTaskActivity :onPause 方法-------------------- hasCode:182738289
OtherSingleTaskActivity :onStop 方法------------------- hasCode:182738289
OtherSingleTaskActivity :onDestroy 方法------------------- hasCode:182738289
複製代碼
咱們能夠看到在SingleTask啓動模式下
日誌
com.hugo.wanandroid I/OtherSingleTaskActivity: [hugo] OtherSingleTaskActivity :onCreate:OtherSingleTaskActivity hasCode:153472021 TaskId:210 TaskAffinity:com.hugo.OtherSingleTaskActivity
com.hugo.reviewbasic I/BaseActivity: [hugo] OtherSingleTaskActivity :onCreate:OtherSingleTaskActivity hasCode:97368138 TaskId:210 TaskNum:2 TaskAffinity:com.hugo.OtherSingleTaskActivity
複製代碼
咱們能夠在圖中看到ComponenApp中的一個Activity和個人測試App的OtherSingleTaskActivity 設置在了同一個任務棧 因此在我先打開ComponenApp的Activity按Home鍵回到桌面在在個人測試App打開OtherSingleTaskActivity 時不會從新建立一個新的任務棧而是獲取了ComponenApp啓動Activity時建立的任務棧(日誌中的==TaskId:210==),並把OtherSingleTaskActivity的實例存入這個任務棧,而後把整個任務移動到回退堆棧的頂部,這時咱們點返回後,顯示的不是SingleTaskActivity,而是ComponenApp中的Activity,在點擊返回時纔會返回到SingleTaskActivity,而這是ComponenApp中的Activity也已經被關閉並銷燬。
這種模式與SingleTask模式基本同樣,只是系統不會將任何其餘的Activity啓動到包含實例的任務棧中,該Activity始終是其任務棧中惟一僅有的成員;由此Activity啓動的任何Activity均在其餘的任務棧中打開。
以下圖所示:
提示:若是咱們在第10步時用Standard模式啓動一個Activity,系統會從新建立一個新的task任務棧來存儲該Activity的實例。
下面是按照上面步驟的日誌:
MainActivity :onCreate 方法-------------------------
MainActivity :onCreate:MainActivity hasCode:53162219 TaskId:221 TaskNum:1 TaskAffinity:com.hugo.reviewbasic
MainActivity :onStart 方法------------------ hasCode:53162219
MainActivity :onResume 方法-------------------- hasCode:53162219
MainActivity :onPause 方法-------------------- hasCode:53162219
SingleInstanceActivity :onCreate 方法-------------------------
SingleInstanceActivity :onCreate:SingleInstanceActivity hasCode:35048165 TaskId:222 TaskNum:1 TaskAffinity:com.hugo.reviewbasic
SingleInstanceActivity :onStart 方法------------------ hasCode:35048165
SingleInstanceActivity :onResume 方法-------------------- hasCode:35048165
MainActivity :onSaveInstanceState 方法------------------ hasCode:53162219
MainActivity :onStop 方法------------------- hasCode:53162219
SingleInstanceActivity :onPause 方法-------------------- hasCode:35048165
OtherActivity1 :onCreate 方法-------------------------
OtherActivity1 :onCreate:OtherActivity1 hasCode:220012746 TaskId:221 TaskNum:2 TaskAffinity:com.hugo.reviewbasic
OtherActivity1 :onStart 方法------------------ hasCode:220012746
OtherActivity1 :onResume 方法-------------------- hasCode:220012746
SingleInstanceActivity :onSaveInstanceState 方法------------------ hasCode:35048165
SingleInstanceActivity :onStop 方法------------------- hasCode:35048165
OtherActivity1 :onPause 方法-------------------- hasCode:220012746
OtherSingleInstanceActivity :onCreate 方法-------------------------
OtherSingleInstanceActivity :onCreate:OtherSingleInstanceActivity hasCode:245363070 TaskId:223 TaskNum:1 TaskAffinity:con.hugo.instance1
OtherSingleInstanceActivity :onStart 方法------------------ hasCode:245363070
OtherSingleInstanceActivity :onResume 方法-------------------- hasCode:245363070
OtherActivity1 :onSaveInstanceState 方法------------------ hasCode:220012746
OtherActivity1 :onStop 方法------------------- hasCode:220012746
OtherSingleInstanceActivity :onPause 方法-------------------- hasCode:245363070
OtherActivity1 :onCreate 方法-------------------------
OtherActivity1 :onCreate:OtherActivity1 hasCode:87192460 TaskId:221 TaskNum:3 TaskAffinity:com.hugo.reviewbasic
OtherActivity1 :onStart 方法------------------ hasCode:87192460
OtherActivity1 :onResume 方法-------------------- hasCode:87192460
OtherSingleInstanceActivity :onSaveInstanceState 方法------------------ hasCode:245363070
OtherSingleInstanceActivity :onStop 方法------------------- hasCode:245363070
OtherActivity1 :onPause 方法-------------------- hasCode:87192460
SingleInstanceActivity :onNewIntent 方法-------------------- hasCode:35048165
SingleInstanceActivity :onNewIntent:SingleInstanceActivity hasCode:35048165 TaskId:222 TaskNum:1 TaskAffinity:com.hugo.reviewbasic
SingleInstanceActivity :onRestart 方法------------------- hasCode:35048165
SingleInstanceActivity :onStart 方法------------------ hasCode:35048165
SingleInstanceActivity :onResume 方法-------------------- hasCode:35048165
OtherActivity1 :onSaveInstanceState 方法------------------ hasCode:87192460
OtherActivity1 :onStop 方法------------------- hasCode:87192460
SingleInstanceActivity :onPause 方法-------------------- hasCode:35048165
OtherActivity1 :onRestart 方法------------------- hasCode:87192460
OtherActivity1 :onStart 方法------------------ hasCode:87192460
OtherActivity1 :onResume 方法-------------------- hasCode:87192460
SingleInstanceActivity :onStop 方法------------------- hasCode:35048165
SingleInstanceActivity :onDestroy 方法------------------- hasCode:35048165
OtherActivity1 :onPause 方法-------------------- hasCode:87192460
OtherActivity1 :onRestart 方法------------------- hasCode:220012746
OtherActivity1 :onStart 方法------------------ hasCode:220012746
OtherActivity1 :onResume 方法-------------------- hasCode:220012746
OtherActivity1 :onStop 方法------------------- hasCode:87192460
OtherActivity1 :onDestroy 方法------------------- hasCode:87192460
OtherActivity1 :onPause 方法-------------------- hasCode:220012746
MainActivity :onRestart 方法------------------- hasCode:53162219
MainActivity :onStart 方法------------------ hasCode:53162219
MainActivity :onResume 方法-------------------- hasCode:53162219
OtherActivity1 :onStop 方法------------------- hasCode:220012746
OtherActivity1 :onDestroy 方法------------------- hasCode:220012746
MainActivity :onPause 方法-------------------- hasCode:53162219
OtherSingleInstanceActivity :onRestart 方法------------------- hasCode:245363070
OtherSingleInstanceActivity :onStart 方法------------------ hasCode:245363070
OtherSingleInstanceActivity :onResume 方法-------------------- hasCode:245363070
MainActivity :onStop 方法------------------- hasCode:53162219
MainActivity :onDestroy 方法------------------- hasCode:53162219
OtherSingleInstanceActivity :onPause 方法-------------------- hasCode:245363070
OtherSingleInstanceActivity :onStop 方法------------------- hasCode:245363070
OtherSingleInstanceActivity :onDestroy 方法------------------- hasCode:245363070
複製代碼
能夠看出SingleInstance啓動模式基本和SingleTask一致,區別就是SingleInstance的棧類只能存在一個自己實例,不能存在其餘Activity的實例,而SingleTask的棧內能夠存在其餘Activity的實例。
下面是官方的說明:
用例 | 啓動模式 | 多個實例? | 註釋 |
---|---|---|---|
大多數 Activity 的正常啓動 | 「standard 」 |
是 | 默認值。系統始終會在目標任務中建立新的 Activity 實例並向其傳送 Intent。 |
「singleTop 」 |
有條件 | 若是目標任務的頂部已存在一個 Activity 實例,則系統會經過調用該實例的 onNewIntent() 方法向其傳送 Intent,而不是建立新的 Activity 實例。 |
|
專用啓動 (不建議用做常規用途) |
「singleTask 」 |
否 | 系統在新任務的根位置建立 Activity 並向其傳送 Intent。 不過,若是已存在一個 Activity 實例,則系統會經過調用該實例的 onNewIntent() 方法向其傳送 Intent,而不是建立新的 Activity 實例。 |
「singleInstance 」 |
否 | 與「singleTask" 」相同,只是系統不會將任何其餘 Activity 啓動到包含實例的任務中。 該 Activity 始終是其任務惟一僅有的成員。 |
使用Intent標誌返回設置啓動模式能夠是用多種標誌本文只簡介其中比較長用的幾種,想知道更多請點擊 這個連接 查看。
使用例子以下:
val intent =Intent(this,SingleInstanceActivity::class.java)
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
startActivity(intent)
複製代碼
在新任務中啓動Activity。若是該Activity已經啓動,則該Activity所在的任務轉到前臺並恢復其最後狀態,同時調用 ==onNewIntent()== 返回傳入Intent。
這個標誌會和前文中 清單設置launchMode 的「SingleTask」 的行爲相同。
若是正在啓動的Activity是當前Activity(位於返回棧的頂部),則回調現有實例調用 ==onNewIntent()== 方法傳入Intent,而不會建立新的實例。
這個標誌和前文中 清單設置launchMode 的 「SingleTop」 的行爲相同。
若是正在啓動的Activity已在當前任務中運行,則會銷燬當前任務頂部的全部Activity,並經過 onNewIntent() 返回鍵Intent傳遞給該Activity的實例(如今位於頂部),而不是啓動該Activity的新實例。
若是該Activity在其餘任務棧中已有實例或沒有實例,可是在當前任務棧中沒有,那麼系統會從新建立一個實例存入當前任務棧中。
若是啓動的Activity 的啓動模式爲「Standard」,則該Activity也會從堆棧中移除銷燬,並在其位置從新建立一個新實例,以便處理傳入的Intent。這是由於當啓動模式爲「Standard」時,將始終爲新Intent建立新實例。
「關聯」是用於指示Activity優先屬於那個任務棧,默認狀況下,同一應用中的全部Activity彼此關聯。所以,默認狀況下,同一應用中的全部Activity優先位於相同任務中。不過能夠修改Activity的默認關聯。在不一樣應用中定義的Activity能夠共享關聯,或者能夠在同一個應用中定義的Activity分配不一樣的任務關聯。
設置以下:
<activity android:name=".singleInstance.OtherSingleInstanceActivity" android:launchMode="singleInstance" android:taskAffinity="con.hugo.instance1"/>
複製代碼
在Android5.0之前使用startActivityForResult() 啓動 SingleTask 和SingleInstance 模式的Activity 會出現 一啓動就在onActivityResult()方法中收到回調的問題 日誌以下:
MainActivity :onPause 方法-------------------- hasCode:-1660511584
MainActivity :onActivityResult 獲取數據:null requestCode:10001
MainActivity :onResume 方法-------------------- hasCode:-1660511584
MainActivity :onPause 方法-------------------- hasCode:-1660511584
SingleTaskActivity :onCreate 方法-------------------------
SingleTaskActivity :onCreate:SingleTaskActivity hasCode:-1659844560 TaskId:9 TaskNum:-1 TaskAffinity:com.hugo.reviewbasic
SingleTaskActivity :onStart 方法------------------ hasCode:-1659844560
SingleTaskActivity :onResume 方法-------------------- hasCode:-1659844560
MainActivity :onSaveInstanceState 方法------------------ hasCode:-1660511584
MainActivity :onStop 方法------------------- hasCode:-1660511584
複製代碼
能夠看到在新的SingleTaskActivity還沒建立以前MainActivity就已經收到了回調並獲取焦點而後立刻又失去焦點。而後SingleTaskActivity才建立。
在5.0之後(包含)就不會出現這個狀況了
日誌以下:
MainActivity :onPause 方法-------------------- hasCode:56699745
SingleInstanceActivity :onCreate 方法-------------------------
SingleInstanceActivity :onCreate:SingleInstanceActivity hasCode:156403808 TaskId:249 TaskNum:2 TaskAffinity:com.hugo.aaaaaaaaaaa
SingleInstanceActivity :onStart 方法------------------ hasCode:156403808
SingleInstanceActivity :onResume 方法-------------------- hasCode:156403808
MainActivity :onSaveInstanceState 方法------------------ hasCode:56699745
MainActivity :onStop 方法------------------- hasCode:56699745
MainActivity :onRestart 方法------------------- hasCode:56699745
MainActivity :onStart 方法------------------ hasCode:56699745
MainActivity :onActivityResult 獲取數據:null requestCode:10002
MainActivity :onResume 方法-------------------- hasCode:56699745
MainActivity :onPause 方法-------------------- hasCode:56699745
MainActivity :onStop 方法------------------- hasCode:56699745
MainActivity :onDestroy 方法------------------- hasCode:56699745
SingleInstanceActivity :onStop 方法------------------- hasCode:156403808
SingleInstanceActivity :onDestroy 方法------------------- hasCode:156403808
複製代碼
能夠看到在5.0之後是能夠正常返回的。==可是啓動模式已經失去了作用==。SingleInstance啓動模式下的Activity所在任務棧只能有惟一一個該Activity的實例,可是在日誌中咱們看到在這個任務棧中有2個實例。因此咱們能夠肯定在Android5.0以後爲了保證回調的功能,若是是startActivityForResult()啓動的Activity,那麼不論是設置的SingleTask仍是SingleInstance都不會去建立新的任務棧,而是建立實例存入該任務棧中。因此在5.0以後沒有出現那個一啓動就回調的問題。
注意:若是你在開發關於這個的問題記得向下兼容。
這個例子的代碼在這裏