SideEffect用在什么场景

一句话定位

SideEffect 用来把 Compose 中的状态同步给「组合之外」的对象或系统 ------它在每次成功重组后执行,没有 key,也没有清理回调。

核心特征:

  • 首次进入组合 + 后续每次真实发生重组时都会执行;
  • 运行在主线程的 apply 阶段,同步执行;
  • 没有 key 参数,无法做到"只有某个值变化才执行"。

典型使用场景

1. 同步给 Presenter / 传统 View(混合开发最常见)

Compose 之外的对象不会参与重组,需要手动把状态推给它:

kotlin 复制代码
class SearchPresenter {
    private var keyword: String = ""
    fun updateKeyword(value: String) { keyword = value }
}

@Composable
fun SearchContent(presenter: SearchPresenter) {
    var keyword by rememberSaveable { mutableStateOf("") }

    TextField(value = keyword, onValueChange = { keyword = it })

    // 每次 keyword 引起重组后,同步给非 Compose 的 Presenter
    SideEffect {
        presenter.updateKeyword(keyword)
    }
}

同理可用于同步给 AndroidView 里持有的老控件、地图 SDK、播放器实例等。

2. 调用平台 API 更新非 Compose 的 UI

kotlin 复制代码
@Composable
fun DetailScreen(title: String, toolbar: Toolbar) {
    SideEffect {
        toolbar.title = title          // 传统 View,而不是 Compose 的 TopAppBar
    }
}

例如更新 Activity.title、Window 状态栏属性、外部 TabLayout 文案等。

3. 埋点 / 日志上报

把当前 UI 状态同步给外部分析系统:

kotlin 复制代码
@Composable
fun ProductScreen(state: ProductUiState, analytics: Analytics) {
    SideEffect {
        analytics.updateContext(state.productId, state.tab)
    }
}

⚠️ 注意:如果要做"每次进入页面只上报一次 "的曝光埋点,应该用 LaunchedEffect(Unit) 或 DisposableEffect,而不是 SideEffect(它会重复执行)。


与前面几个 Effect 的选择

需求 用什么
执行异步任务、请求数据、监听 Flow LaunchedEffect(key)
注册监听器 / 观察者,离开时需要释放 DisposableEffect(key)
每次重组后,把状态同步给组合之外的对象 SideEffect
缓存计算结果,不产生副作用 remember / derivedStateOf

判断口诀:

  • 需要 协程 / 挂起 → LaunchedEffect
  • 需要 注册 + 反注册 → DisposableEffect
  • 只是 同步给外部对象 → SideEffect
  • 只想 值变化时执行一次 → 用带 key 的 LaunchedEffect / DisposableEffect

注意事项

kotlin 复制代码
// ❌ 反例
SideEffect {
    scope.launch { repository.fetch() }   // 异步任务请用 LaunchedEffect
    _uiState.value = newState             // 不要用副作用反向写 Compose 状态
    analytics.track("click")              // 每次重组都会触发,会重复上报
}
  1. 必须轻量、幂等:重组可能被跳过、合并,也可能因重试重复执行,不要依赖"刚好执行一次"。
  2. 不要做 IO / 阻塞 / 耗时操作:它运行在主线程,会拖慢重组。
  3. 不用于管理生命周期 :它没有 onDispose,组件离开组合时不会通知你。
  4. 块内读 state 不会建立重组依赖 :需要被观察的状态要在 composable 主体里读,再把结果带进 SideEffect。
相关推荐
Android-Flutter3 天前
Compose 管理状态 详解
android·compose
撩得Android一次心动8 天前
Jetpack Compose 知识点整理2【个人用】
android·笔记·学习·kotlin·compose
Android-Flutter10 天前
Compose 什么叫重组?怎么样触发重组?
android·compose
stevenzqzq18 天前
mvi的理解
android·compose
Android-Flutter1 个月前
Compose CompositionLocal 详解
android·compose
Android-Flutter1 个月前
android compose 知识点
android·compose
撩得Android一次心动2 个月前
Jetpack Compose 知识点整理1【个人用】
android·学习·kotlin·android jetpack·compose
stevenzqzq2 个月前
Compose 生命周期与副作用的核心奥秘
android·compose
XiaoLeisj2 个月前
Jetpack Compose 知识点
android·kotlin·android jetpack·compose