repeatOnLifecycle 与 Flow · AndroidX 源码指南
AAndroidX 源码指南
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()(持续收集)。

常见陷阱

  • collectAsState vs collectAsStateWithLifecycle:前者后台持续收集,后者跟随生命周期——用后者。
  • collect 顺序:多个 collect 必须 launch 并发。
  • repeatOnLifecycle 放错 scope:必须用 lifecycleScopeLifecycleOwner 相关 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()

相关页面