1. 一句话总纲
- SideEffect:每次重组后,同步执行一段代码
- LaunchedEffect:key 变化时,启动协程做异步任务
- DisposableEffect:带清理 / 销毁的 effect,离开重组范围时自动执行收尾
2. SideEffect
核心
每次重组成功后 → 同步执行 → 无 key → 不能 suspend
特点
- 每次重组必跑
- 同步执行,不能 delay、不能挂起
- 没有 key,无法 “只执行一次”
- 适合极轻量操作:埋点、日志、更新外部对象
典型场景
SideEffect {
// 埋点/日志
Analytics.log("show_page")
// 更新外部非 compose 状态
audioView.setAmplitude(amp)
}
禁忌
- 不要更新 State(会循环重组)
- 不要做耗时、异步操作
2. LaunchedEffect
核心
key 变化时 → 启动协程 → 可 suspend → 可取消重启
特点
- 依赖
key,key 不变就不重启 - 内部是协程作用域,可以:delay、launch、await
- 重组时如果 key 没变,不会重新执行
- 离开组合时自动取消协程
典型场景
LaunchedEffect(userId) {
// 网络请求
val data = api.getUser(userId)
// 动画
animateTo(1f)
// 定时任务
while(true) {
delay(300)
updateWave()
}
}
常用技巧
LaunchedEffect(Unit)= 只执行一次(类似 onCreate)LaunchedEffect(xxx)= xxx 变化时重新执行
3. DisposableEffect
核心
带清理 / 解绑的 effect → 进入执行 onEnter + 离开 /key 变化执行 onDispose
特点
- 和 LaunchedEffect 一样受 key 控制
- 必须实现 onDispose {}
- 适合:注册 / 反注册、订阅 / 取消订阅、创建 / 销毁
典型场景
DisposableEffect(lifecycle) {
// 进入时:注册
lifecycle.addObserver(observer)
// 离开/key 变化时:清理
onDispose {
lifecycle.removeObserver(observer)
}
}
最常用场景
- 注册广播
- 传感器监听
- 自定义 View 回调绑定 / 解绑
- 播放、录音资源管理
4. 三张表彻底分清(面试 + 开发必备)
① 执行时机
| Effect | 触发时机 | 是否受控 |
|---|---|---|
| SideEffect | 每次重组后 | ❌ 不受控 |
| LaunchedEffect | key 变化 / 首次进入 | ✅ key 控制 |
| DisposableEffect | key 变化 / 首次进入 | ✅ key 控制 |
② 能力限制
| Effect | 可 suspend | 可清理 | 同步 / 异步 |
|---|---|---|---|
| SideEffect | ❌ 不可 | ❌ 无 | 同步 |
| LaunchedEffect | ✅ 可以 | ❌ 无 | 协程异步 |
| DisposableEffect | ❌ 不可(但可配合协程) | ✅ onDispose | 同步 |
③ 最适合场景
| Effect | 典型业务 |
|---|---|
| SideEffect | 埋点、日志、更新外部对象 |
| LaunchedEffect | 请求接口、动画、轮询、定时任务 |
| DisposableEffect | 注册 / 反注册、订阅、资源释放 |
5. 一套代码对比(秒懂)
@Composable
fun WaveScreen(amp: Float) {
// 1. 每次重组都跑:同步副作用
SideEffect {
Log.d("wave", "重组了")
}
// 2. key 变化跑协程:轮询振幅
LaunchedEffect(Unit) {
while(true) {
delay(300)
// 更新波形
}
}
// 3. 带清理:注册录音监听
DisposableEffect(Unit) {
val callback = RecordCallback()
recorder.register(callback)
onDispose {
recorder.unregister(callback)
}
}
}
6. 终极选择口诀
- 只要轻量同步、每次重组都要 → SideEffect
- 只要异步 / 协程 / 定时 / 请求 → LaunchedEffect
- 只要注册订阅、必须手动清理 → DisposableEffect