一、它到底是干嘛的?
一句话:让 Flow 的收集(collect)只在页面可见时执行,页面不可见时自动取消,避免内存泄漏、浪费资源、后台回调导致崩溃。
它是 Android 官方 唯一推荐 的 Flow 收集方式,专门用来解决:
- Flow 收集生命周期泄漏
- 页面退到后台还在收到数据
- 多次进入页面导致重复 collect
- 生命周期安全问题
二、生命周期对应关系
你只需要记住两个最常用:
1. Lifecycle.State.STARTED
- 页面 可见 时:开始 collect
- 页面 不可见(按 Home、切到别的 App):自动取消收集
- 页面 再次可见:重新启动收集
2. Lifecycle.State.RESUMED
- 页面 可交互、在前台 时才收集
- 弹出对话框、分屏等半可见状态:不收集
三、最典型使用场景(全部覆盖)
场景 1:收集 StateFlow / Flow 更新 UI(最常用)
所有 UI 观察 ViewModel 数据,必须用它。
kotlin
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.uiState.collect { state ->
// 只在页面可见时执行
updateUi(state)
}
}
}
为什么必须这样写?
- 页面不可见 → collect 自动停
- 页面回来 → 自动恢复
- 不会泄漏
- 不会后台更新 UI 导致崩溃
场景 2:一个页面收集多个 Flow
多个 Flow 都要生命周期安全,全部包在同一个 repeatOnLifecycle 里:
kotlin
lifecycleScope.launch {
repeatOnLifecycle(STARTED) {
launch {
viewModel.uiState.collect { ... }
}
launch {
viewModel.eventFlow.collect { ... }
}
}
}
场景 3:列表、分页、搜索等持续数据流
例如:
- Paging3
- 搜索框实时搜索
- 蓝牙 / 位置回调
- 传感器数据
只要是 Flow 且要更新 UI,都必须用 repeatOnLifecycle(STARTED)
场景 4:防止 “页面关闭了还在执行”
比如:
- 请求网络返回后更新 View
- 定时器 Flow
- 无限循环的 Flow
不用它,就会:
- 内存泄漏
- 崩溃
- 耗电、耗流量
四、它和直接 lifecycleScope.launch 有什么区别?(重点)
错误写法(很多人踩坑)
kotlin
// ❌ 危险!页面销毁了还在收集,泄漏+崩溃
lifecycleScope.launch {
viewModel.uiState.collect { ... }
}
问题:
lifecycleScope只是在销毁时 最后取消- 但页面不可见时 仍然在运行
- 后台收到数据 → 更新 UI → 崩溃
正确写法 ✅
kotlin
lifecycleScope.launch {
repeatOnLifecycle(STARTED) {
viewModel.uiState.collect { ... }
}
}
行为:
- 可见 → 运行
- 不可见 → 停止
- 再回来 → 重新开始
- 销毁 → 彻底取消
五、repeatOnLifecycle 内部执行机制(超清晰)
plaintext
onStart() → 进入 STARTED → 开始执行代码块
onStop() → 退出 STARTED → 取消代码块(包括 collect)
再次onStart → 重新执行代码块
它会重复执行代码块,所以叫 repeatOnLifecycle
六、适用 vs 不适用场景
✅ 适用(必须用)
- StateFlow 观察 UI 状态
- SharedFlow 观察一次性事件
- 网络请求 Flow
- 数据库观察 Flow
- 搜索、列表、分页数据流
❌ 不适用(不要用)
- 只执行一次的请求(不 collect,直接 launch 就行)
- 不需要生命周期控制的后台任务
- 不需要随页面可见性启停的任务
七、repeatOnLifecycle 在compose中使用吗?
非常重要:Compose 里不使用 repeatOnLifecycle!
我给你用最清晰、最不会错的方式讲清楚:
1、 结论先说
- 在 XML 视图(Fragment/Activity)
-
✅ 使用:
repeatOnLifecycle(STARTED)
-
- 在 Jetpack Compose 视图
- ❌ 不使用
repeatOnLifecycle - ✅ 取而代之使用:
collectAsStateWithLifecycle
- ❌ 不使用
2、为什么 Compose 不用 repeatOnLifecycle?
因为:
repeatOnLifecycle是给 命令式 XML 用的- Compose 是 声明式 UI,自带重组、生命周期感知
collectAsStateWithLifecycle()是官方专门为 Compose 打造的- 它内部自动处理:STARTED/STOPPED 生命周期,比手动写更安全
3、 官方最新标准(必须用)
kotlin
val uiState by viewModel.uiState.collectAsStateWithLifecycle()
八、完整 Compose 示例(直接复制)
ViewModel
kotlin
class MyViewModel : ViewModel() {
private val _uiState = MutableStateFlow(UiState())
val uiState: StateFlow<UiState> = _uiState.asStateFlow()
}
Compose UI
kotlin
@Composable
fun HomeScreen(viewModel: MyViewModel = viewModel()) {
// ✅ 生命周期安全收集
val uiState by viewModel.uiState.collectAsStateWithLifecycle()
Column {
if (uiState.isLoading) {
CircularProgressIndicator()
}
Text(uiState.data ?: "无数据")
}
}