Activity啟動模式 1. Activity啟動模式介紹 1.1 任務棧 在Android開發中,任務棧(Task Stack)是一個非常重要的概念,主要用於管理應用程式中的Activity及其啟動模式。它幫助開發者瞭解當用戶在不同應用之間切換,或者應用內部不同Activity之間跳轉時,系統如 ...
Activity啟動模式
1. Activity啟動模式介紹
1.1 任務棧
在Android開發中,任務棧(Task Stack)是一個非常重要的概念,主要用於管理應用程式中的Activity及其啟動模式。它幫助開發者瞭解當用戶在不同應用之間切換,或者應用內部不同Activity之間跳轉時,系統如何管理這些Activity的生命周期與顯示行為。任務棧是一個後進先出(LIFO, Last In First Out)的堆棧結構,用來存放應用程式啟動的Activity。當用戶啟動一個新的Activity時,系統會將其壓入任務棧頂部,用戶可以通過返回按鈕(back)將棧頂的Activity彈出(銷毀),顯示當前棧頂的Activity。系統中可以存在多個任務棧,當前所在任務棧的棧頂Activity實例會被顯示。
1.2 啟動模式分類
在Android開發中,啟動模式(Launch Mode)是指系統在管理Activity時如何處理該Activity的啟動和任務棧的行為。它決定了一個Activity在被啟動時是否創建新的實例、如何與已有的任務棧互動,以及在應用導航中如何管理Activity的狀態。當你啟動一個Activity時,系統需要決定是否創建一個新的Activity實例,或者復用已經存在的實例,這些行為是由啟動模式控制的。其中standard模式、singleTop模式和singleInstancePerTask模式都是針對當前任務棧的;singleTask和singleInstance模式是針對系統全局的。啟動模式的設置分為靜態設置和動態設置兩種。
1.2.1 standard
standard(標準模式)是Activity預設的啟動模式,即當前Activity未顯式設置啟動模式情況下,其啟動模式為standard。在standard模式下,每次啟動該Activity系統都會創建一個新的實例(instance)並壓入當前任務棧頂,不論是否已有相同Activity實例存在。Activity實例數量沒有限制,具體取決於任務棧深度。該模式適用於大多數情景,例如在一個應用中打開多個頁面。其模式原理如下圖。
1.2.2 singleTop
當Activity啟動模式設置為singleTop時,系統啟動該Activity時若發現當前任務棧棧頂(並非系統全局)為該Activity實例,則會直接復用該實例(調用onNewIntent()方法)而不會重新創建;若當前任務棧棧頂不為該Activity實例時,則會創建新的實例無論當前或其他任務棧中是否已存在對應實例。該模式適用於在同一任務中頻繁跳轉回當前頁面的場景,例如從通知點擊進入消息頁面。其模式原理圖如下。
1.2.3 singleTask
當Activity啟動模式設置為singleTask時,系統啟動該Activity時若發現存在一個任務棧(系統全局)中存在該Activity實例時,則會直接復用該實例(調用onNewIntent()方法)而不會重新創建,同時將該任務棧中位於該實例之上的其它Activity實例都將會被彈出棧,該實例作為當前任務棧棧頂;若所有任務棧中都不存在該Activity實例時,則會在當前任務棧中創建該Activity實例作為棧頂。該實例在所有任務棧中唯一存在。該模式適用於“主頁”類Activity,或者需要保證該Activity在整個應用中只有一個實例的場景,如應用的主界面、設置界面。其模式原理圖如下。
1.2.4 singleInstance
當Activity啟動模式設置為singleInstance時,系統全局只允許存在該Activity的一個實例,並且該Activity將獨占一個任務棧。系統啟動該Activity時,若所有任務棧中都不存在該Activity實例時,系統會使用一個獨立的任務棧,併在該棧中創建該Activity實例,該任務棧只用於管理該Activity實例,唯一存在;當該Activity實例已經存在於獨立的任務棧中時,系統會直接復用該實例,該實例在所有任務棧中唯一存在。該模式適用於鎖屏頁面、視頻播放等需要獨立管理的Activity,防止干擾。其模式原理圖如下。
1.2.5 singleInstancePerTask
singleInstancePerTask 是 Android API 31(即 Android 12)引入的一種新的啟動模式。這種模式可以看作是對 singleInstance 和 singleTask 啟動模式的一種補充,目的是增強應用在多任務場景中的靈活性。當Activity啟動模式設置為singleInstancePerTask時,系統啟動該Activity時若發現當前任務棧中存在該Activity實例時,則會直接復用該實例;若不存在,則在當前任務棧中創建新的實例作為棧頂。該模式適用於需要跨多個任務棧獨立運行,但每個任務棧中只允許一個實例的 Activity,如多視窗操作中,每個視窗都需要獨立的 Activity 實例。
2. 靜態設置啟動模式
2.1 通過AndroidManifest.xml中的launchMode屬性
靜態設置是指在AndroidManifest.xml文件中,通過在
點擊查看代碼
<activity android:name=".MainActivity"
android:launchMode="singleTop">
</activity>
2.2 靜態設置特點
- 編譯時確定:在編譯時指定,運行時無法更改。
- 全局適用:對於該Activity的所有啟動方式,都會按照指定的啟動模式處理。
- 可讀性高:在Manifest文件中一目瞭然,有助於維護。
3. 動態設置啟動模式
3.1 通過Intent的Flags屬性
動態設置是指在代碼中,通過為Intent添加特定的Flag(標誌)來指定Activity的啟動行為。這些Flag會影響Activity的啟動模式和任務棧的管理。示例如下:
點擊查看代碼
#kotlin
val intent = Intent(this, MainActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP
startActivity(intent)
3.2 常用Flag介紹
- FLAG_ACTIVITY_NEW_TASK:這個標誌會告訴系統為新啟動的 Activity 創建一個新的任務棧(Task),如果該 Activity 已經存在於某個棧中,它將復用現有的任務棧並將 Activity 添加到棧頂。該標誌在啟動一個新的 Activity 時是強制性的,特別是在從非 Activity 上下文(如 Service 或 BroadcastReceiver)啟動 Activity 時。
- FLAG_ACTIVITY_SINGLE_TOP:如果啟動的 Activity 已經在棧頂,則復用它的實例,而不是創建新的實例。如果該 Activity 不在棧頂,系統將創建一個新的實例並將其推到棧頂。這個標誌類似於在 launchMode 中設置 singleTop。
- FLAG_ACTIVITY_CLEAR_TOP:當啟動的 Activity 已經存在於任務棧中時,它會清除這個 Activity 之上的所有其他 Activity。然後,系統會將這個 Activity 置於棧頂並復用它的實例。這通常與 FLAG_ACTIVITY_NEW_TASK 結合使用。
- FLAG_ACTIVITY_CLEAR_TASK:這個標誌會清除目標 Activity 所在的整個任務棧(Task)。所有位於該任務棧中的 Activity 都會被銷毀,然後啟動目標 Activity 作為新的棧根。
- FLAG_ACTIVITY_REORDER_TO_FRONT:如果目標 Activity 已經在任務棧中,但不是棧頂,系統會將它移動到棧頂,而不銷毀棧中的其他 Activity,也不會創建新的實例。
- FLAG_ACTIVITY_NO_HISTORY:該標誌表示啟動的 Activity 不會被添加到任務棧中,也就是說當用戶離開這個 Activity 後,系統將不會保存它的狀態。這常用於啟動短暫的頁面,如登錄頁面、廣告頁面等。
- FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS:這個標誌會防止啟動的 Activity 出現在“最近任務”(Recents)中。即使用戶通過多任務按鈕查看任務列表,該 Activity 也不會出現在列表中。
3.3 onNewIntent() 方法
當使用動態設置的Flags復用已經存在的Activity時,系統不會調用onCreate()方法,因為沒有創建新的實例。相反,系統會調用onNewIntent()方法。你可以在onNewIntent()方法中處理傳遞給Activity的新的Intent。
點擊查看代碼
#Kotlin
override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
// 處理新Intent
}
3.4 動態設置特點
- 靈活性高:動態設置允許根據應用運行時的不同場景靈活控制Activity的啟動行為。例如,你可以在接收到不同的Intent時,根據用戶操作動態決定是否復用現有的Activity實例或清理任務棧。
- 更精細的控制:通過組合多個Flags,動態設置可以提供比靜態設置更為細緻的行為控制,滿足複雜的應用需求。
4. 總結
在實際開發中,可以結合靜態和動態設置。例如,為某些核心頁面設置靜態啟動模式,同時在代碼中根據業務邏輯使用Intent Flags動態調整特定場景下的啟動行為。