Compose 副作用(Effect)高频面试题

3 阅读4分钟

1. SideEffect 是什么?什么时候用?

标准答案:

  • SideEffect 是 Compose 提供的同步副作用 API,会在每次重组成功后同步执行。
  • 不支持协程、没有 key、每次重组都会执行
  • 用于执行不影响 UI、不更新 State的轻量操作:埋点、日志、更新外部原生 View、通知第三方 SDK 状态变化。
  • 目的是避免在重组作用域内直接写副作用导致不可预期的多次执行

2. LaunchedEffect 作用?key 的意义?

标准答案:

  • LaunchedEffect 用于在 Compose 中启动协程执行异步任务,如网络请求、动画、轮询、延时任务。
  • key 是控制协程重启的标识:key 不变,协程不重启;key 变化,旧协程取消并重启新协程。
  • LaunchedEffect(Unit) 表示只在组件首次进入组合时执行一次
  • 组件离开组合时,协程自动取消,不会泄漏。

3. DisposableEffect 什么时候用?和 LaunchedEffect 区别?

标准答案:

  • DisposableEffect 用于需要成对注册 / 释放的场景,必须实现 onDispose 做清理。

  • 比如:注册广播、传感器、监听、回调、订阅,在组件销毁或 key 变化时反注册、释放资源。

  • 区别:

    • LaunchedEffect 侧重异步任务,自动取消协程;
    • DisposableEffect 侧重资源管理,必须手动写清理逻辑。

4. 为什么要用 rememberUpdatedState?解决什么问题?

标准答案:

  • 解决长生命周期协程 / 回调捕获旧参数的问题。
  • 当 LaunchedEffect 用 Unit 做 key 只执行一次时,协程内部会持有参数初始值,外部参数更新后协程内依然是旧值。
  • rememberUpdatedState 会把变量包装成 State 引用,让协程 / 回调永远读取最新值,且不会触发协程重启

5. produceState 是什么?和 LaunchedEffect 区别?

标准答案:

  • produceState 是 **将异步数据源转换为 Compose State的 API**,内部是协程,返回State`。

  • 可以通过 value = 更新数据,驱动 UI 重组;支持 awaitDispose 做资源清理。

  • 区别:

    • LaunchedEffect 只执行任务,不返回状态,需要手动维护 mutableStateOf
    • produceState 自带 State 管理,代码更简洁,适合异步数据转 UI 状态。

6. snapshotFlow 作用?使用场景?

标准答案:

  • snapshotFlow 可以将 Compose State 的变化转换成 Kotlin Flow
  • 每次 State 读取的值发生变化,Flow 就会自动发射新值。
  • 适合对 State 做防抖、过滤、映射、合并、延迟等响应式处理,最典型场景是搜索框防抖

7. LaunchedEffect (key1 = Unit) 一定只执行一次吗?

标准答案:

  • 不一定。
  • 如果组件被完全重组(recreate) ,或者父组件强制重组导致当前组件离开组合再重新进入LaunchedEffect(Unit) 会再次执行。
  • 它的 “一次” 是组合生命周期内的一次,不是整个页面生命周期。

8. SideEffect 里可以更新 State 吗?

标准答案: 不可以,会导致死循环重组。

  • SideEffect 每次重组后执行,如果内部更新 State,会触发新一轮重组,反复无限执行。
  • 它只能用于无状态更新的副作用。

9. LaunchedEffect 和 rememberCoroutineScope 怎么选?

标准答案:

  • LaunchedEffect:跟随组件生命周期,自动取消,适合页面初始化、轮询、监听。
  • rememberCoroutineScope:返回一个手动控制的协程作用域,常用于点击事件等用户触发的协程
  • 原则:生命周期跟随组件 → LaunchedEffect;手动触发 → rememberCoroutineScope

10. Compose 副作用设计核心思想是什么?

标准答案:

  • 副作用与组合生命周期绑定,自动取消、自动清理,避免泄漏。
  • 声明式控制执行时机,用 key 驱动重启。
  • 分离 UI 描述与副作用,保证重组行为可预测。

11. 实战题:长协程要读最新参数,怎么做?

标准答案: 用 rememberUpdatedState 包装外部参数,在协程内读取包装后的值,保证永远是最新的,且不重启协程。


12. 实战题:搜索框防抖怎么实现?

标准答案: 用 snapshotFlow 监听输入 State,配合 Flow 的 debounce 操作符实现防抖,在 LaunchedEffect 中收集结果并请求搜索。


一张表秒选 API

表格

需求选哪个
每次重组都要执行同步逻辑SideEffect
异步 / 协程 / 请求 / 动画LaunchedEffect
注册 / 反注册 / 释放资源DisposableEffect
长协程读最新外部参数rememberUpdatedState
异步数据转 State 给 UIproduceState
防抖 / 过滤 / 合并 StatesnapshotFlow