一、整体分类总览
1. 重组同步副作用
- SideEffect
2. 协程异步任务
- LaunchedEffect
- produceState
3. 带清理 / 订阅
- DisposableEffect
4. 保持最新值(解决旧值捕获)
- rememberUpdatedState
5. State ↔ Flow 互转
- snapshotFlow
- collectAsStateWithLifecycle
二、逐个核心 API 速查(最强总结版)
1) SideEffect
一句话:每次重组后,同步执行一段非 UI 逻辑
触发:每次重组必跑
协程:❌ 不能 suspend
清理:❌ 无典型场景
- 埋点、日志
- 更新外部原生 View(AudioWaveView)
- 避免直接在重组域写副作用
禁忌
- 不要更新 State(会死循环)
- 不要做耗时 / 异步
2) LaunchedEffect(key)
一句话:key 变化时,启动协程做异步任务
触发:key 变化 / 首次进入
协程:✅ 可 suspend
清理:自动取消协程
典型场景
- 网络请求
- 动画
- 轮询、定时任务
- 长循环(录音振幅更新)
技巧
LaunchedEffect(Unit):只执行一次- key 越多,控制越精细
3) DisposableEffect(key)
一句话:带onDispose的 Effect,必须成对 “注册 / 释放”
触发:key 变化 / 首次进入
协程:❌ 不能 suspend
清理:✅ onDispose{} 必须写
典型场景
- 注册 / 反注册监听
- 广播、传感器
- 第三方 SDK 回调绑定
- 播放器、录音器释放
4) rememberUpdatedState
一句话:包一个值,让长协程 / 回调永远读到最新版
触发:外部值自动同步
重组:❌ 不触发重组
解决问题:LaunchedEffect 里捕获旧值
典型场景
- 长循环协程 + 外部参数变化
- 注册的回调里要用最新参数
- 录音振幅、播放进度等持续更新值
5) produceState
一句话:异步数据 → 自动生成 Compose State
返回:State<T>
协程:✅ suspend
清理:✅ awaitDispose{}
典型场景
- 网络请求转 UI 状态
- 数据库监听
- 录音振幅轮询转 State
- 订阅 / 回调转 State
优势
不用自己写 mutableStateOf + LaunchedEffect
6) snapshotFlow
一句话:Compose State 变化 → 转换成 Kotlin Flow
能力:防抖、过滤、map、合并、延迟
典型场景
- 搜索框防抖 debounce
- 状态过滤 / 转换
- 多 State 合并监听
- 动画平滑、波形抖动抑制
核心
State 变 → Flow 自动发射新值
7) collectAsStateWithLifecycle
一句话:Flow → 转成生命周期安全的 Compose State
场景:ViewModel 暴露 Flow,UI 收集并显示
优势
- 生命周期安全
- 避免页面不可见时浪费资源
三、终极选择流程图(按这个选永远不错)
第一步:是同步还是异步?
- **同步轻量操作(埋点 / 日志 / 更新外部对象)**→ SideEffect
- 异步 / 协程 / 延迟 / 请求 / 循环→ 第二步
第二步:要不要返回 State 给 UI 用?
- 要返回 State 直接显示→ produceState
- 只做任务,不输出 State→ LaunchedEffect
第三步:是否需要注册 / 订阅 / 释放?
- **必须手动清理(注册 / 反注册)**→ DisposableEffect
第四步:协程 / 回调里参数会过时吗?
- 会,需要永远读最新值→ rememberUpdatedState
第五步:需要防抖 / 过滤 / 合并状态?
- 是→ snapshotFlow
四、6 大 API 最强对比表(面试直接背)
| API | 触发时机 | 协程 | 清理 | 核心用途 |
|---|---|---|---|---|
| SideEffect | 每次重组后 | ❌ | ❌ | 同步副作用 |
| LaunchedEffect | key 变化 | ✅ | 自动取消 | 异步任务 |
| DisposableEffect | key 变化 | ❌ | ✅onDispose | 订阅 / 释放 |
| rememberUpdatedState | 值自动同步 | ❌ | ❌ | 保持值最新 |
| produceState | key 变化 | ✅ | ✅awaitDispose | 异步→State |
| snapshotFlow | State 变化 | ✅配合协程 | 自动取消 | State 转 Flow 防抖 |
五、和你业务最相关的组合示例(录音波形)
@Composable
fun WaveView(recorder: AudioRecorder) {
// 1. 轮询振幅 → 转 State
val amplitude by produceState(0f, recorder) {
while (recorder.isRecording) {
delay(300)
val amp = recorder.currentRecordMaxAmplitude / 32767f
value = amp.coerceIn(0f, 1f)
}
}
// 2. 保证拿到最新值
val currentAmp by rememberUpdatedState(amplitude)
// 3. State 转 Flow → 防抖
LaunchedEffect(Unit) {
snapshotFlow { currentAmp }
.debounce(100)
.collect {
// 4. 同步更新外部 View
SideEffect {
audioWaveView.setAmplitude(it)
}
}
}
}
六、一句话终极口诀
重组同步用 Side,
异步任务用 Launch,
订阅释放用 Disposable,
参数过时用 Updated,
异步转状态用 Produce,
防抖过滤用 Flow。