compose中 RememberObserver / RetainObserver 是什么
摘要: RememberObserver和RetainObserver是Jetpack Compose中用于管理状态对象生命周期的底层接口,分别通过remember和retain触发回调。它们解决了对象构造与实际使用不同步的问题(如资源泄漏风险),但官方明确反对在业务代码中直接使用。推荐通过DisposableEffect、ViewModel等高层API管理副作用。仅建议在开发基础库、强绑定资源的
·
一、RememberObserver / RetainObserver 是什么?
先给一句官方级定义:
它们是“状态对象的生命周期回调接口”,不是 UI API,也不是业务 API。
换句话说:
它们是给“状态对象自己”用的,不是给 Composable 直接调用的。
RememberObserver
当一个对象被 remember { ... } 保存时,Compose 允许这个对象接收 组合生命周期回调。
interface RememberObserver {
fun onRemembered()
fun onForgotten()
fun onAbandoned()
}
生命周期语义(非常重要)
| 回调 | 含义 |
|---|---|
onRemembered() |
对象真正进入 Composition |
onForgotten() |
对象被移出 Composition |
onAbandoned() |
组合被中断,对象从未真正被使用 |
RetainObserver
当对象通过 retain { ... } 保存(跨配置变化)时,使用的是 Retain 生命周期。
interface RetainObserver {
fun onRetained()
fun onRetired()
fun onUnused()
}
生命周期语义
| 回调 | 含义 |
|---|---|
onRetained() |
对象被保留用于下一个配置 |
onRetired() |
对象不再被保留 |
onUnused() |
retain 发生但对象未被真正使用 |
二、它们到底解决了什么问题?
核心问题一句话:
Compose 中,对象的构造 ≠ 对象真正被使用
为什么这是个问题?
Compose 在以下情况下会:
- 创建对象
- 但又立刻放弃
- 或因为重组 / 分支变化而丢弃
val manager = remember {
Manager() // ⚠️ 构造函数可能被调用
}
👉 构造函数调用,并不意味着它会长期存在
错误做法(官方明确反对)
class Manager {
init {
startListening() // ❌ 非常危险
}
}
如果对象马上被 abandoned:
- 监听已启动
- 但永远没有清理
- 泄漏 / 重复注册
三、正确用法(官方推荐)
1️⃣ RememberObserver 的正确姿势
class Manager : RememberObserver {
override fun onRemembered() {
startListening() // ✅ 真正被使用时
}
override fun onForgotten() {
stopListening() // ✅ 被移除时清理
}
override fun onAbandoned() {
// 一般什么都不做
}
}
@Composable
fun Screen() {
val manager = remember { Manager() }
}
2️⃣ RetainObserver 的正确姿势
class Player : RetainObserver {
override fun onRetained() {
prepare()
}
override fun onRetired() {
release()
}
override fun onUnused() {
// retain 但没用到
}
}
@Composable
fun PlayerScreen() {
val player = retain { Player() }
}
四、那我平时为啥根本没见过它们?
因为官方 不希望在业务代码里用它们
这是重点。
官方推荐的替代方案(更熟)
| 场景 | 推荐方式 |
|---|---|
| 启动副作用 | LaunchedEffect |
| 注册 / 反注册 | DisposableEffect |
| 长期状态 | ViewModel |
| 资源管理 | rememberCoroutineScope |
举个对比(非常重要)
❌ 用 RememberObserver(业务里不推荐)
class UiTracker : RememberObserver { ... }
✅ 用 DisposableEffect(官方推荐)
@Composable
fun Screen() {
DisposableEffect(Unit) {
startTracking()
onDispose { stopTracking() }
}
}
官方为什么不鼓励用 Observer?
- API 偏底层
- 极易被误用
- 难测试
- 不直观
- Composable 级别的 Effect 已经覆盖 99% 需求
五、那什么时候“真的需要”它们?
只有这 3 种情况(非常少)
1️⃣ 写库 / 框架 / 基础组件
- 自定义状态容器
- Compose 基础设施
- UI 工具库
👉 不是在写业务代码
2️⃣ 状态对象本身必须管理副作用
例如:
- 播放器
- 渲染引擎
- 原生资源句柄
👉 副作用和对象本身强绑定
3️⃣ retain + 资源管理(高级用法)
retain { Engine() }
且:
- Engine 自己知道何时 prepare / release
- 不能交给 Composable 层
六、为什么公司项目里“没用到”是好现象?
因为这说明:
- 项目在用 正确的高层 API
- 副作用在 Composable 层管理
- 状态和资源职责清晰
- 没滥用底层机制
👉 这不是落后,是成熟
七、给一个“工程师级结论”
RememberObserver / RetainObserver
是 Compose 的“底层生命周期钩子”,
而不是日常开发工具。
如果你在业务代码里大量看到它们:
- ⚠️ 设计可能有问题
更多推荐



所有评论(0)