Lifecycle
应用基础 · androidx.lifecycle
repeatOnLifecycle 与 Flow2.12.0-alpha01
让收集协程随可见状态重启,而不是在后台持续工作;collectLatest 与 stateIn 的配合。
最后更新 2026-08-01
推荐的数据流
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.uiState.collect { state ->
render(state)
}
}
}行为:
- 外层协程挂起等待整个生命周期(不阻塞 UI)。
- 进入
STARTED时启动 block,block 内的collect开始接收。 - 低于
STARTED(如onPause)时取消 block——collect 停止,释放资源。 - 再次进入
STARTED时重新启动 block——重新收集,拿到最新值。
为什么不用 if (lifecycle.currentState.isAtLeast(STARTED)):那只检查一次,后续状态变化不会持续跟踪。
同时收集多个 Flow
repeatOnLifecycle(Lifecycle.State.STARTED) {
launch { viewModel.uiState.collect(::render) }
launch { viewModel.events.collect(::handleEvent) }
}collect 是挂起函数,永不返回。多个收集必须用子协程并发;顺序写两个 collect 第二个永远不会执行。
flowWithLifecycle:单条流门控
val gated = viewModel.uiState
.flowWithLifecycle(lifecycle, Lifecycle.State.STARTED)
// 用法:在任意 scope 收集
lifecycleScope.launch {
gated.collect { render(it) }
}flowWithLifecycle(lifecycle, minActiveState) 返回一个新 Flow:生命周期低于门限时不发射(暂停),恢复后继续。区别:
| 场景 | 选择 |
|---|---|
| 单条流 + 继续操作符链 | flowWithLifecycle |
| 多条流并发收集 | repeatOnLifecycle(结构清晰) |
注意 flowWithLifecycle 的暂停语义:低于门限时上游不发射但不取消(与 repeatOnLifecycle 的取消重启不同)。
collectLatest:跳过期数据
repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.uiState.collectLatest { state ->
// 如果处理期间来了新值,取消当前处理
renderExpensive(state)
}
}高频更新的 Flow(进度条、输入)用 collectLatest 避免堆积过期处理。
UI 与 ViewModel 的两种模式
// 模式 1:Flow → collect(推荐,UI 层控制时机)
repeatOnLifecycle(STARTED) { viewModel.uiState.collect(::render) }
// 模式 2:StateFlow → collectAsState(Compose)
val state by viewModel.uiState.collectAsStateWithLifecycle()Compose 中用 collectAsStateWithLifecycle()(lifecycle-runtime-compose)——它内部就是 repeatOnLifecycle + state 收集,UI 不可见时停止收集。不要用普通 collectAsState()(持续收集)。
常见陷阱
collectAsStatevscollectAsStateWithLifecycle:前者后台持续收集,后者跟随生命周期——用后者。- collect 顺序:多个 collect 必须 launch 并发。
repeatOnLifecycle放错 scope:必须用lifecycleScope或LifecycleOwner相关 scope,协程才能在销毁时取消。viewModelScope里不要 repeatOnLifecycle:ViewModel 没有 lifecycle,这是 UI 层的职责。
复制即用
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import androidx.lifecycle.flowWithLifecycle
import kotlinx.coroutines.launch
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.uiState.collectLatest { state ->
updateUi(state)
}
}
}
}
}要点
repeatOnLifecycle(STARTED) { collect }:进入 STARTED 收集,低于时取消,再进入重启。- 多流并发收集;单流门控用
flowWithLifecycle。 - 高频流用
collectLatest跳过期。 - Compose 用
collectAsStateWithLifecycle(),不是collectAsState()。