一、先一句话记住
SideEffect = 专门用来在 Compose 中执行 “非界面副作用” 的函数
什么叫副作用?
- 发送 Analytics 埋点
- 更新外部变量
- 调用第三方 SDK 方法
- 打印日志
- 执行一次性操作
- 不影响 UI、不返回 UI 状态的逻辑
规则:Compose 重组(Recomposition)时,SideEffect 一定会执行!
二、官方定义
kotlin
fun SideEffect(block: () -> Unit)
- 每次重组成功后同步执行
- 在 Composition 范围内执行
- 不能挂起(不能写 suspend)
- 没有 key,每次重组都跑
三、最核心特点 ✅
- 每次重组都会执行
- 同步执行(马上跑)
- 不能执行异步 / 协程
- 没有 key,不受控
- 专门用于非 UI 副作用
四、最标准使用示例
@Composable
fun MyComposable(name: String) {
// 每次重组都会执行
SideEffect {
// 埋点
Log.d("Compose", "组件重组了,name = $name")
// 更新外部变量
externalViewModel.updateName(name)
}
Text(text = name)
}
五、SideEffect 最常用场景
1. 日志 / 埋点(每次重组上报)
kotlin
SideEffect {
Analytics.trackPage("HomePage")
}
2. 更新外部非 Compose 状态
kotlin
SideEffect {
// 通知外部系统状态变化
audioWaveView.setAmplitude(amplitude)
}
3. 执行一次性同步操作
kotlin
SideEffect {
// 执行SDK同步方法
NimSDK.updateStatus(status)
}
4. 避免在重组中直接执行副作用(非常重要)
❌ 错误:
kotlin
@Composable
fun Test() {
// ❌ 直接写在这里会在重组时无限执行!
Log.d("xxx", "重组")
Text("123")
}
✅ 正确:
kotlin
@Composable
fun Test() {
SideEffect {
Log.d("xxx", "重组") // ✅ 安全、受控
}
Text("123")
}
六、SideEffect 与 LaunchedEffect 区别(面试必考)
| 特性 | SideEffect | LaunchedEffect |
|---|---|---|
| 执行时机 | 每次重组后同步 | key 变化时异步 |
| 是否可挂起 | ❌ 不可以 | ✅ 可以(suspend) |
| 是否受控 | ❌ 每次重组都跑 | ✅ key 控制 |
| 用途 | 同步副作用 | 异步任务(网络、协程) |
| 例子 | 埋点、更新外部变量 | 请求接口、播放动画 |
七、SideEffect 重要规则
- 不能在里面执行耗时操作
- 不能更新 Compose State(会导致死循环)
- 每次重组都会跑
- 必须是同步操作
- 专门用于和 UI 无关的逻辑
八、什么时候必须用 SideEffect?
- 你要执行非 UI 操作
- 这个操作必须在组件成功显示后执行
- 这个操作每次重组都需要执行
- 你不想它因为重组而被漏掉
九、最简单记忆口诀
重组完,同步跑,无协程,副作用。