當使用者瀏覽、離開及返回應用程式時,應用程式中的 Activity 執行個體會在生命週期中轉換不同狀態。Activity 類別提供多項回呼,可讓活動瞭解狀態何時變更,或是系統何時建立、停止或恢復活動,或是終止活動所在的程序。
在生命週期回呼方法中,您可以宣告活動在使用者離開及重新進入時的行為。舉例來說,如果您要建構串流影片播放器,當使用者切換到其他應用程式時,您可以暫停影片並終止網路連線。使用者返回時,您可以重新連線到網路,讓使用者從相同位置繼續觀看影片。
每個回呼都可讓您執行適合特定狀態變更的特定工作。在適當時間執行適當工作,並妥善處理轉場效果,可讓應用程式更穩健且效能更佳。舉例來說,妥善實作生命週期回呼可協助應用程式避免下列情況:
- 使用者使用應用程式時接聽電話或切換至其他應用程式,導致應用程式當機。
- 在使用者未主動使用時耗用寶貴的系統資源。
- 使用者離開應用程式後再返回時,進度會遺失。
- 螢幕在橫向和直向之間旋轉時,應用程式會當機或遺失使用者進度。
本文將詳細說明活動生命週期。本文首先會說明生命週期範例,接著說明每個回呼:執行期間內部會發生什麼情況,以及您需要在回呼期間導入哪些內容。
接著簡要介紹活動狀態與程序遭系統終止的風險之間的關係。最後,本節會討論與活動狀態轉換相關的幾個主題。
如要瞭解如何處理生命週期,包括最佳做法指南,請參閱「Jetpack Compose 中的生命週期」和「儲存 UI 狀態」。如要瞭解如何結合活動和架構元件,建構出完善且品質媲美正式版的應用程式,請參閱「應用程式架構指南」。
活動生命週期概念
如要導覽活動生命週期階段之間的轉場,Activity 類別提供一組六個核心回呼:onCreate、onStart、onResume、onPause、onStop 和 onDestroy。當活動進入新狀態時,系統會叫用這些回呼。
圖 1 以視覺化方式呈現這個範例。

當使用者開始離開活動時,系統會呼叫方法來拆解活動。在某些情況下,活動只會部分拆解,仍會駐留在記憶體中,例如使用者切換到其他應用程式時。在這些情況下,活動仍可返回前景。
如果使用者返回活動,活動會從使用者離開時的狀態繼續執行。但有少數例外情況,應用程式在背景執行時無法啟動活動。
系統是否會終止特定程序及其中的活動,取決於當時的活動狀態。如要進一步瞭解狀態與遭驅逐的風險之間的關係,請參閱「活動狀態和從記憶體中驅逐」一節。
視活動的複雜程度而定,您可能不需要實作所有生命週期方法。不過,請務必瞭解每個手勢,並實作能讓應用程式以使用者預期方式運作的手勢。
Compose 和生命週期
在 Compose 中,請避免直接在活動回呼 (例如 onStart 或 onResume) 中放置商業邏輯或手動設定觀察器。請改用生命週期感知效果和狀態感知觀察器,自動與畫面上的 UI 對齊。
- 生命週期感知收集作業:使用
collectAsStateWithLifecycle從ViewModel中取用流程。當 UI 進入「已啟動」狀態時,這個 API 會自動開始收集資料,並在 UI 進入背景時停止,避免不必要的資源耗用。將流程收集為狀態後,您可以使用LifecycleEffects在發生生命週期事件時執行程式碼。 - 邏輯流程:使用這些 API 時,UI 會透過組合樹狀結構自然地對生命週期狀態做出反應,確保只有在使用者積極與元件互動時,才會執行商業邏輯。
如要進一步瞭解 Compose 和生命週期,請參閱「Jetpack Compose 中的生命週期」。
生命週期回呼
本節提供活動生命週期期間使用的回呼方法概念和實作資訊。
部分動作屬於活動生命週期方法。不過,請在元件中放置實作依附元件動作的程式碼,而不是活動生命週期方法。如要達成這個目標,您必須讓相依元件感知生命週期。如要瞭解如何讓依附元件感知生命週期,請參閱「Jetpack Compose 中的生命週期」。
onCreate
您必須實作這個回呼,系統首次建立活動時會觸發此回呼。活動建立後,會進入「已建立」狀態。在 onCreate 方法中,執行活動整個生命週期只會發生一次的基本應用程式啟動邏輯。
舉例來說,您的實作項目可能會將資料繫結至清單、將活動與 ViewModel 建立關聯,以及例項化某些類別範圍變數。onCreate這個方法會接收 savedInstanceState 參數,這是 Bundle 物件,內含先前儲存的活動狀態。如果活動先前從未存在,Bundle 物件的值會是空值。
如果生命週期感知元件已連結至活動的生命週期,就會收到 ON_CREATE 事件。系統會呼叫以 @OnLifecycleEvent 註解的方法,讓生命週期感知元件執行建立狀態所需的任何設定碼。
以下範例說明如何在最基本的活動中整合 Text 可組合函式:
class ExampleActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { // In here, we can call composables! MaterialTheme { Greeting(name = "compose") } } } } @Composable fun Greeting(name: String) { Text(text = "Hello $name!") }
您的活動不會維持在「已建立」狀態。onCreate 方法執行完畢後,活動會進入「已啟動」狀態,系統會快速接連呼叫 onStart 和 onResume 方法。
onStart
當活動進入「已啟動」狀態時,系統會叫用 onStart。這個呼叫會讓活動對使用者顯示,因為應用程式會準備讓活動進入前景並成為互動式活動。舉例來說,這個方法會初始化維護 UI 的程式碼。
活動進入「已啟動」狀態時,與活動生命週期相關聯的任何生命週期感知元件都會收到 ON_START 事件。
onStart 方法會快速完成,且與「已建立」狀態相同,活動不會停留在「已啟動」狀態。這個回呼完成後,活動會進入「已繼續」狀態,且系統會叫用 onResume 方法。
onResume
當活動進入「已恢復」狀態時,活動會移至前景,且系統會叫用 onResume 回呼。這是指應用程式與使用者互動的狀態。應用程式會維持這個狀態,直到發生某件事導致應用程式失去焦點為止,例如裝置收到來電、使用者前往其他活動,或是裝置螢幕關閉。
活動進入「已恢復」狀態時,繫結至活動生命週期的任何生命週期感知元件都會收到 ON_RESUME 事件。生命週期元件可以在這裡啟用任何需要在元件顯示於前景時執行的功能,例如啟動相機預覽畫面。
發生中斷事件時,活動會進入「暫停」狀態,且系統會叫用 onPause 回呼。
如果活動從「已暫停」狀態返回「已恢復」狀態,系統會再次呼叫 onResume 方法。因此,請實作 onResume,初始化在 onPause 期間發布的元件,並執行任何其他初始化作業,這些作業必須在活動每次進入「已恢復」狀態時執行。
以下是生命週期感知元件的範例,該元件會在收到 ON_RESUME 事件時存取相機:
class CameraComponent : LifecycleObserver {
...
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
fun initializeCamera() {
if (camera == null) {
getCamera()
}
}
...
}
上述程式碼會在 LifecycleObserver 收到 ON_RESUME 事件時初始化相機。不過,在多視窗模式下,即使活動處於暫停狀態,也可能會完全顯示。舉例來說,當應用程式處於多視窗模式,且使用者輕觸不含您活動的視窗時,您的活動會移至「已暫停」狀態。
如果只希望在應用程式「已恢復」時 (顯示在前景並處於活動狀態) 啟用相機,請在先前示範的 ON_RESUME 事件後初始化相機。如要在活動暫停但仍可見時 (例如在多視窗模式下) 保持攝影機運作,請在 ON_START 事件後初始化攝影機。
不過,如果活動處於「已暫停」狀態時相機仍處於啟用狀態,可能會導致其他處於「已恢復」狀態的應用程式無法在多視窗模式下存取相機。有時您可能需要在活動暫停時保持攝影機運作,但這麼做可能會降低整體使用者體驗。
因此,請仔細思考在多視窗模式下,最適合在生命週期的哪個階段控管共用系統資源。如要進一步瞭解如何支援多視窗模式,請參閱「支援多視窗模式」。
無論您選擇在哪個建構事件中執行初始化作業,請務必使用對應的生命週期事件釋出資源。如果在 ON_START 事件後初始化某些項目,請在 ON_STOP 事件後發布或終止該項目。如果在 ON_RESUME 事件後初始化,請在 ON_PAUSE 事件後發布。
上述程式碼片段會將相機初始化程式碼放在生命週期感知元件中。您可以改為直接將這段程式碼放入活動生命週期回呼 (例如 onStart 和 onStop),但我們不建議這麼做。將這項邏輯新增至獨立的生命週期感知元件,即可在多個活動中重複使用該元件,不必複製程式碼。如要瞭解如何建立生命週期感知元件,請參閱「Jetpack Compose 中的生命週期」。
onPause
系統會呼叫這個方法,做為使用者要離開活動的第一個指標,但這不一定表示活動會遭到終止。這表示活動不再位於前景,但如果使用者處於多視窗模式,活動仍會顯示。活動進入這個狀態的原因如下:
- 如「
onResume回呼」一節所述,中斷應用程式執行的事件會暫停目前的活動。這是最常見的情況。 - 在多視窗模式下,一次只會有一個應用程式處於焦點狀態,系統會暫停所有其他應用程式。
- 開啟新的半透明活動 (例如對話方塊) 時,系統會暫停該活動所涵蓋的活動。只要活動部分顯示但未在前景運作,就會保持暫停狀態。
活動移至「已暫停」狀態時,繫結至活動生命週期的任何生命週期感知元件都會收到 ON_PAUSE 事件。生命週期元件可以在這裡停止任何不需要執行的功能 (元件不在前景時),例如停止攝影機預覽。
使用 onPause 方法暫停或調整無法繼續的作業,或是在 Activity 處於「已暫停」狀態時,可能繼續進行的作業,並預期不久後會繼續。
您也可以使用 onPause 方法釋放系統資源、感應器 (例如 GPS) 的控制代碼,或任何會影響電池續航力的資源,前提是活動已暫停,且使用者不需要這些資源。
不過,如 onResume 一節所述,如果應用程式處於多視窗模式,暫停的活動可能仍會完全顯示。建議使用 onStop 而非 onPause,完整釋放或調整 UI 相關資源和作業,以便更妥善支援多視窗模式。
以下範例說明 LifecycleObserver 如何對 ON_PAUSE 事件做出反應,與先前的 ON_RESUME 事件範例相對應,在收到 ON_RESUME 事件後釋出初始化的相機:
class CameraComponent : LifecycleObserver {
...
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
fun releaseCamera() {
camera?.release()
camera = null
}
...
}
這個範例會在 LifecycleObserver 收到 ON_PAUSE 事件後,放置相機釋放程式碼。
onPause 執行時間很短,不一定有足夠時間執行儲存作業。因此,請勿使用 onPause 儲存應用程式或使用者資料、發出網路呼叫,或執行資料庫交易。這類工作可能無法在方法完成前完成。
請改為在 onStop 期間執行高負載關機作業。如要進一步瞭解在 onStop 期間適合執行的作業,請參閱下一節。如要進一步瞭解如何儲存資料,請參閱「儲存及還原狀態」一節。
完成 onPause 方法並不代表活動會離開「已暫停」狀態。活動會維持這個狀態,直到活動恢復或使用者完全看不到活動為止。如果活動恢復,系統會再次叫用 onResume 回呼。
如果活動從「已暫停」狀態返回「已恢復」狀態,系統會將 Activity 執行個體保留在記憶體中,並在系統叫用 onResume 時回呼該執行個體。在此情況下,您不需要重新初始化在任何回呼方法中建立的元件,這些方法會導致 Resumed 狀態。如果活動完全隱藏,系統會呼叫 onStop。
onStop
當活動不再對使用者顯示時,就會進入「已停止」狀態,而系統會叫用 onStop 回呼。如果新啟動的活動會占據整個畫面,就可能發生這種情況。活動即將終止時,系統也會呼叫 onStop。
活動移至「已停止」狀態時,繫結至活動生命週期的任何生命週期感知元件都會收到 ON_STOP 事件。生命週期元件可以在元件未顯示於畫面上時,停止任何不需要執行的功能。
在 onStop 方法中,當應用程式對使用者不可見時,請釋出或調整不需要的資源。舉例來說,應用程式可能會暫停動畫,或從精確位置更新切換為粗略位置更新。使用 onStop 而非 onPause,表示即使使用者在多視窗模式下檢視活動,UI 相關工作仍會繼續。
此外,請使用 onStop 執行 CPU 密集型關機作業。舉例來說,如果找不到更合適的時間將資訊儲存到資料庫,您可能會在 onStop 期間執行這項操作。以下範例顯示 onStop 的實作方式,可將草稿記事的內容儲存至永久儲存空間:
override fun onStop() {
super.onStop()
// Delegate the save operation to the ViewModel, which handles the
// background thread operations (e.g., using Kotlin Coroutines and Room).
noteViewModel.saveDraft()
}
活動進入「已停止」狀態時,Activity 物件會保留在記憶體中:它會維護所有狀態和成員資訊,但不會附加至視窗管理員。活動恢復時,系統會回想這項資訊。
活動處於「已停止」狀態時,可能會返回與使用者互動,也可能執行完畢並消失。如果活動返回,系統會叫用 onRestart。如果 Activity 執行完畢,系統會呼叫 onDestroy。
onDestroy
onDestroy 會在活動刪除前呼叫。系統會基於下列其中一項原因,叫用這個回呼:
- 活動即將結束,原因可能是使用者完全關閉活動,或是活動呼叫
finish。 - 系統因設定變更 (例如旋轉裝置或進入多視窗模式) 而暫時刪除活動。
活動進入已刪除狀態時,與活動生命週期相關聯的任何生命週期感知元件,都會收到 ON_DESTROY 事件。生命週期元件可以在 Activity 遭到刪除前,在這裡清理任何需要的項目。
請勿在 Activity 中加入邏輯,判斷為何要銷毀 Activity,而是使用 ViewModel 物件,存放 Activity 的相關檢視畫面資料。如果 Activity 因設定變更而重新建立,ViewModel 不必執行任何動作,因為系統會保留 ViewModel,並提供給下一個 Activity 執行個體。
如果系統未重新建立 Activity,則 ViewModel 會呼叫 onCleared 方法,以便在刪除前清理任何需要的資料。您可以使用 isFinishing 方法區分這兩種情況。
如果活動即將結束,onDestroy 是活動收到的最後一個生命週期回呼。如果 onDestroy 是因設定變更而呼叫,系統會立即建立新的活動例項,然後在新設定中對該新例項呼叫 onCreate。
onDestroy 回呼會釋出先前回呼未釋出的所有資源,例如 onStop。
活動狀態和從記憶體中清除
系統會在需要釋放 RAM 時終止程序。系統終止特定程序的可能性取決於該程序當時的狀態。而程序狀態則取決於程序中執行的活動狀態。表 1 顯示程序狀態、活動狀態和系統終止程序的可能性之間的關聯。只有在程序未執行其他類型的應用程式元件時,才適用這個表格。
遭殺害的可能性 |
程序狀態 |
最終活動狀態 |
最低 |
前景 (已取得或即將取得焦點) |
已重新啟用 |
低 |
可見 (未聚焦) |
已啟動/已暫停 |
較高 |
背景 (隱形) |
已停止 |
最高 |
空白 |
已刪除 |
表 1. 程序生命週期與活動狀態之間的關係。
系統絕不會直接終止活動來釋放記憶體。而是會終止活動執行的程序,不僅會毀損活動,也會毀損程序中執行的所有其他項目。如要瞭解如何在系統啟動的程序終止時,保留及還原活動的 UI 狀態,請參閱「儲存及還原狀態」一節。
使用者也可以透過「設定」中的「應用程式管理員」終止相應的應用程式,藉此終止程序。
如要進一步瞭解程序,請參閱「程序和執行緒總覽」。
儲存及還原暫時性 UI 狀態
在設定變更 (例如旋轉或切換至多視窗模式) 的過程中,使用者會期望活動的 UI 狀態保持不變。不過,當這類設定變更發生時,系統會刪除活動,清除任何儲存在活動例項中的 UI 狀態。
同樣地,如果暫時切換至其他應用程式後再返回,使用者也預期 UI 狀態將維持不變。不過,當使用者離開且活動停止時,系統可能會刪除應用程式的程序。
當系統限制導致 Activity 遭到終止時,請使用 ViewModel (適用於複雜的商業邏輯和畫面狀態)、Jetpack Compose rememberSaveable API (適用於輕量 UI 狀態) 和/或本機儲存空間,保留使用者的暫時性 UI 狀態。如要進一步瞭解使用者期望與系統行為的比較,以及如何在系統啟動的活動和程序終止時,盡可能保留複雜的 UI 狀態資料,請參閱「儲存 UI 狀態」。
rememberSaveable 會在幕後將狀態組合在一起,自動在設定變更和系統啟動的程序終止後保留狀態,提供流暢的體驗,不必使用活動層級的樣板。
執行個體狀態
在某些情況下,活動會因應用程式的正常行為而遭到刪除,例如使用者按下「返回」按鈕,或活動呼叫 finish 方法,自行發出刪除信號。
當使用者按下返回鍵或活動自行結束時,活動就會遭到刪除,系統和使用者對該 Activity 執行個體的概念都會永遠消失。在這些情況下,使用者的期望與系統行為一致,您不需要進行任何額外工作。
不過,如果系統因系統限制 (例如設定變更或記憶體壓力) 而刪除活動,雖然實際的 Activity 例項會消失,但系統會記住該例項存在過。如果使用者嘗試返回活動,系統會使用一組儲存的資料建立該活動的新例項,這些資料說明活動遭到終止時的狀態。
系統用來還原先前狀態的儲存資料稱為「例項狀態」。在幕後,這是一組鍵/值組合。根據預設,系統會使用例項狀態儲存 UI 版面配置的基本資訊,例如使用者輸入的文字或捲動位置。
您可以使用 rememberSaveable 連結至這項系統行為。如果活動例項遭到刪除並重新建立,系統會自動還原以 rememberSaveable 包裝的任何 UI 狀態,您不必編寫額外的活動層級程式碼。
不過,您的活動可能會有更複雜的狀態資訊 (例如使用者資料、網路回應或追蹤使用者進度的成員變數),您會想要還原這些資訊。例項狀態機制 (以及延伸的 rememberSaveable) 不適合保留大量資料,因為這類機制需要在主執行緒上序列化,並耗用系統程序記憶體。
如要保留大量資料,請一併使用永久本機儲存空間、ViewModel 類別和 Compose 狀態提升,如「儲存 UI 狀態」一文所述。
使用 rememberSaveable 儲存簡單輕巧的 UI 狀態
活動開始停止時,系統會準備將狀態資訊儲存至執行個體狀態套件。如要連結至這項系統行為,請直接在可組合函式中使用 rememberSaveable。rememberSaveable 會在活動重新建立時,自動儲存及還原暫時性 UI 狀態,例如使用者輸入的文字或捲動位置。
如要儲存自訂的輕量狀態資訊 (例如使用者在遊戲中的進度),請使用 rememberSaveable 宣告狀態。Compose 架構會在幕後處理序列化作業,將資料序列化至執行個體狀態套件:
var userTypedQuery by rememberSaveable(typedQuery, stateSaver = TextFieldValue.Saver) { mutableStateOf( TextFieldValue(text = typedQuery, selection = TextRange(typedQuery.length)) ) }
如要儲存持續性資料 (例如使用者偏好設定或資料庫資料),請在活動位於前景時把握適當時機。如果沒有這類機會,請在 onStop 方法期間儲存持續性資料。
使用儲存的例項狀態還原活動 UI 狀態
先前活動遭到終止後,系統會自動重建活動並還原狀態。使用 rememberSaveable 時,您不需要編寫任何明確的還原邏輯、檢查空值組合,或覆寫活動回呼。初始化及儲存狀態的程式碼也會在活動返回時,順暢地還原狀態:
var userTypedQuery by rememberSaveable(typedQuery, stateSaver = TextFieldValue.Saver) { mutableStateOf( TextFieldValue(text = typedQuery, selection = TextRange(typedQuery.length)) ) }
活動和導覽
在應用程式的生命週期中,可能會多次在不同畫面間轉換,例如使用者輕觸裝置的返回按鈕或選取新目的地時。當代 Android 應用程式通常採用單一活動架構。應用程式不會為每個畫面啟動新的 Activity,而是會代管單一 Activity,並使用 Navigation 元件,在該活動中替換可組合的畫面。
如要瞭解如何實作以 Compose 為優先的現代導覽功能,請參閱 Jetpack Compose Navigation 3 程式庫指南。
從其他活動啟動活動
活動有時可能需要啟動另一個活動。舉例來說,當應用程式需要從目前的畫面移至新畫面時,就會有這種需求。
視活動是否要從即將啟動的新活動取得結果而定,您可以使用 startActivity 方法或 startActivityForResult 方法啟動新活動。無論是上述哪種情況,您都要傳入 Intent 物件。
Intent 物件會指定要啟動的確切活動,或是說明要執行的動作類型。系統會為您選取適當的活動,甚至可能來自其他應用程式。Intent 物件也可以攜帶少量資料,供啟動的活動使用。如要進一步瞭解 Intent 類別,請參閱「意圖和意圖篩選器」。
startActivity
如果新啟動的活動不需要傳回結果,目前的活動可以呼叫 startActivity 方法來啟動活動。
在自己的應用程式中工作時,您通常只需要啟動已知的活動。舉例來說,下列程式碼片段說明如何啟動名為 SignInActivity 的活動。
val context = LocalContext.current
Button(onClick = {
val intent = Intent(context, SignInActivity::class.java)
context.startActivity(intent)
}) {
Text("Sign In")
}
啟動外部活動
雖然內部應用程式導覽是由 Navigation 處理,但 Activity 偶爾還是需要啟動其他活動。通常是想利用外部應用程式執行特定動作時,例如開啟網路瀏覽器、傳送電子郵件或拍照。
如要達成這個目標,請使用 Intent 物件說明要執行的動作類型,系統就會從其他應用程式啟動適當的活動。
舉例來說,如要讓使用者傳送電子郵件訊息,可以建立下列意圖:
val intent = Intent(Intent.ACTION_SEND).apply {
putExtra(Intent.EXTRA_EMAIL, recipientArray)
}
startActivity(intent)
如要啟動外部活動並取得結果 (例如要求相機應用程式拍攝相片並傳回圖片),請使用新版 Activity result API,而非已淘汰的 startActivityForResult 回呼。
協調活動
當一個活動啟動另一個活動時,兩者都會經歷生命週期轉換。第一個活動會停止運作並進入「已暫停」或「已停止」狀態,而另一個活動則會建立。如果這些活動共用儲存至磁碟或其他位置的資料,請務必瞭解,在建立第二個活動之前,第一個活動不會完全停止。而是啟動第二個作業的程序,會與停止第一個作業的程序重疊。
生命週期回呼的順序已明確定義,特別是當兩個活動位於相同程序 (也就是相同應用程式) 中,且其中一個活動啟動另一個活動時。以下是活動 A 啟動活動 B 時發生的作業順序:
- 活動 A 的
onPause方法會執行。 - 活動 B 的
onCreate、onStart和onResume方法會依序執行。活動 B 現在具有使用者焦點。 - 如果活動 A 不再顯示於畫面上,系統會執行其
onStop方法。
這一連串的生命週期回呼可讓您管理從一個活動到另一個活動的資訊轉換。
其他資源
如要進一步瞭解活動生命週期,請參閱下列其他資源: