Android Lifecycle 生命週期感知元件
在 Android 開發中,管理 Activity 或 Fragment 的生命週期 (Lifecycle) 是一項核心且具備挑戰性的任務。傳統的做法是將大量的邏輯,例如連線啟動、資料監聽、資源釋放等,直接寫在 Activity 的生命週期回呼方法(如 onStart(), onStop())中。
這種傳統寫法常會導致以下問題:
- 程式碼臃腫且耦合度高:Activity 肩負過多職責,邏輯難以重用與測試。
- 資源洩漏風險:如果忘記在對應的生命週期釋放資源(例如在
onStop忘記斷開資料庫連線),會導致記憶體洩漏 (Memory Leak) 或應用程式崩潰。
Android Lifecycle Library 透過觀察者模式 (Observer Pattern) 解決了這個痛點,讓元件具備「生命週期感知能力」,實現邏輯的解耦與自我管理。
關鍵角色
- LifecycleOwner:擁有生命週期的物件,最常見的就是 Activity 和 Fragment。
- LifecycleObserver:生命週期的觀察者,用來監聽 LifecycleOwner 的狀態變化並執行相應邏輯。
生命週期事件 (Events) 與狀態 (States)
理解生命週期的關鍵在於區分「事件」與「狀態」。你可以將其想像成一個狀態機的轉換過程:
- Event (事件):框架觸發的「轉換動作」。例如
ON_START表示轉換開始。 - State (狀態):轉換完成後的「當前處境」。例如
STARTED表示元件已就緒。

| 事件 (Events) | 說明 | 狀態改變 (States) |
|---|---|---|
| ON_CREATE | 元件初始化完成。 | 進入 CREATED |
| ON_START | 元件即將在螢幕上出現。 | 進入 STARTED |
| ON_RESUME | 元件已在最前景,可供使用者互動。 | 進入 RESUMED |
| ON_PAUSE | 元件失去焦點,但仍部分可見。 | 保持 STARTED |
| ON_STOP | 元件完全不可見。 | 回到 CREATED |
| ON_DESTROY | 元件被銷毀,資源應即刻釋放。 | 進入 DESTROYED |
實作生命週期觀察者
雖然早期我們常用 LifecycleEventObserver,但現在 Android 官方更推薦使用 DefaultLifecycleObserver,它的架構更清晰且易於維護。
使用 DefaultLifecycleObserver (推薦)
透過實作 DefaultLifecycleObserver,你可以只覆寫你需要的生命週期方法:
// 定義一個具備生命週期感知的播放器觀察者
class MyVideoObserver(private val player: VideoPlayer) : DefaultLifecycleObserver {
override fun onResume(owner: LifecycleOwner) {
// 當 Activity 回到前台,自動開始播放
player.play()
}
override fun onPause(owner: LifecycleOwner) {
// 當 Activity 進入背景,自動暫停以節省資源
player.pause()
}
override fun onDestroy(owner: LifecycleOwner) {
// 當 Activity 徹底銷毀,完全釋放資源
player.release()
}
}
註冊觀察者
在 Activity 或 Fragment 中,只需透過 lifecycle.addObserver() 即可完成綁定:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// 註冊觀察者後,播放器邏輯將自動與 Activity 生命週期同步
lifecycle.addObserver(MyVideoObserver(player))
}
}
在 Jetpack Compose 中整合
在 Compose 開發中,組件(Composable)通常需要根據生命週期執行 Side Effects,這時我們會結合 Side Effect API 來處理。
LocalLifecycleOwner
在 Composable 函式中,你可以透過 LocalLifecycleOwner.current 快速取得當前的生命週期持有者。
使用 DisposableEffect 進行監聽
適用於需要手動註冊/移除監聽器的場景,例如統計埋點或特定硬體 API:
@Composable
fun LifecycleTracker(lifecycleOwner: LifecycleOwner = LocalLifecycleOwner.current) {
DisposableEffect(lifecycleOwner) {
// 建立一個臨時觀察者
val observer = object : DefaultLifecycleObserver {
override fun onStart(owner: LifecycleOwner) {
println("使用者進入了畫面")
}
}
// 註冊觀察者
lifecycleOwner.lifecycle.addObserver(observer)
// 清理機制:當 Composable 被移除或 lifecycleOwner 改變時執行
onDispose {
lifecycleOwner.lifecycle.removeObserver(observer)
}
}
}
數據流的生命週期安全
在 UI 層面收集資料流(如 Flow)時,必須確保在背景時停止收集,以避免不必要的 CPU 與電力消耗。
repeatOnLifecycle
repeatOnLifecycle 讓 Flow 的收集能與 Activity/Fragment 的生命週期「同步」。它會在你指定的生命週期狀態(例如 STARTED)下啟動協程,並在離開該狀態時自動取消:
- 當進入 onStart 時: 自動啟動協程,開始 collect 資料。
- 當進入 onStop 時: 自動取消協程,停止收集,節省資源。
- 當再次回到 onStart 時: 重新啟動協程,再次開始收集。
@Composable
fun ProfileScreen(viewModel: ProfileViewModel) {
val lifecycleOwner = LocalLifecycleOwner.current
LaunchedEffect(lifecycleOwner) {
// 當生命週期至少處於 STARTED 時,執行區塊
// 當生命週期進入 STOPPED 時,區塊內的協程會被自動取消
lifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
// 在這裡安全地收集 Flow
viewModel.userEvents.collect { event ->
// 只有在 UI 可見時才處理事件
}
}
}
}
collectAsStateWithLifecycle (極力推薦)
這是目前最推薦將 Flow 轉為 Compose State 的方法。它內部封裝了 repeatOnLifecycle 的邏輯,使用最為簡便。
使用它需要先確保你的 build.gradle 有導入以下依賴:
implementation("androidx.lifecycle:lifecycle-runtime-compose:2.6.0") // 或更新版本
應用範例:
// ViewModel 部分
class UserViewModel : ViewModel() {
private val _userName = MutableStateFlow("載入中...")
val userName: StateFlow<String> = _userName.asStateFlow()
fun updateName(newName: String) {
_userName.value = newName
}
}
// Compose UI 部分
@Composable
fun UserProfileScreen(viewModel: UserViewModel = viewModel()) {
// 關鍵行:以生命週期感知的方式收集 StateFlow
// 當 App 進入背景時,它會自動停止收集以節省資源
val name by viewModel.userName.collectAsStateWithLifecycle()
Column(modifier = Modifier.padding(16.dp)) {
Text(text = "目前使用者: $name")
Button(onClick = { viewModel.updateName("Gemini") }) {
Text("更改名字")
}
}
}
- 當 App 進入背景(不可見)時,它會自動暫停上游節點的資料發射。
- 當 App 回到前台時,它會自動恢復收集,確保資料永遠是最新的且節省資源。
生命週期開發最佳實務
- 邏輯與 Activity 分離:將與生命週期相關的業務邏輯封裝在
LifecycleObserver中,保持 Activity 的簡潔。 - ViewModel 不應感知 UI 生命週期:ViewModel 應該是純粹的資料提供者,不應直接持有
LifecycleOwner或觀察 UI 狀態。 - 成對操作:如果需要在
ON_START初始化資源,務必在ON_STOP進行回收;ON_RESUME則對應ON_PAUSE。 - 優先使用 collectAsStateWithLifecycle:這是處理 Compose 資料流最穩定且效能最佳的實踐方式。