用途
本技能解决 Jetpack Compose 中副作用 API 的选择问题:在 LaunchedEffect、DisposableEffect、SideEffect、rememberUpdatedState,以及 skydoves/compose-effects 库新增的 RememberedEffect、ViewModelStoreScope 之间,挑选“最省资源且语义正确”的那一个。选错 API 会浪费协程作用域、泄漏监听器,或静默丢弃最新版本的回调。
主要能力
- 提供决策树:需要协程用 LaunchedEffect;需要无协程的 setup/cleanup 用 DisposableEffect;需要同步响应 key 变化用 RememberedEffect;长生命周期 LaunchedEffect 消费可能变化的回调时用 rememberUpdatedState 包裹;LazyColumn 每行需要独立 ViewModel 时用 ViewModelStoreScope;每次成功组合后都要运行的副作用用 SideEffect。
- 给出正误代码对照模式:过期回调、非协程订阅者、同步 key 反应、逐行 ViewModel、一次性工作(remember 对比 LaunchedEffect(Unit))。
- 列出强制规则与验证方法,包括用 @TraceRecomposition 检查 effect 运行次数、在 onDispose 中打日志、验证 rememberUpdatedState 生效、检查行级 VM 的 init/onCleared 等。
使用方式
按决策树选择 API,并遵循强制规则:长生命周期 LaunchedEffect 中消费外部回调必须用 rememberUpdatedState;非协程订阅者优先 DisposableEffect 而非 LaunchedEffect + try/finally;一次性且需跨重组存活的工作用 remember 而非 LaunchedEffect(Unit);不要用 SideEffect 做逐帧或分配型工作;effect 的 key 必须覆盖所有应触发重启的闭包值;在 LazyColumn/LazyRow 项内调用 hiltViewModel() 且需要独立 VM 时,必须用 ViewModelStoreScope(key = 稳定 id)。RememberedEffect 需要依赖 com.github.skydoves:compose-effects;ViewModelStoreScope 需要 com.github.skydoves:compose-effects-viewmodel,导入路径为 com.skydoves.compose.effects.viewmodel.ViewModelStoreScope;配合 Hilt 还需 androidx.hilt:hilt-navigation-compose。
适用场景
用户询问该选哪个 effect API,或 LaunchedEffect 意外重启;长生命周期 LaunchedEffect 调用到父级已更新的过期回调;非 Compose 订阅者(监听器、观察者、广播接收器、GL surface)需要在进入组合时 setup、在 key 变化或退出时 teardown;组合只需同步响应 key 变化而协程作用域属于过度设计;LazyColumn 行需要自己的 ViewModel 实例;调试意外的 effect 重启、监听器泄漏或 SideEffect 的逐帧分配。
限制
不适用于:从一个 State 纯派生另一个 State(应使用 derivedStateOf);收集来自组合外部的 flow(应使用 collectAsStateWithLifecycle);必须跨重组存活且不重跑的一次性计算(应使用 remember)。前置要求包括熟悉 Compose 组合生命周期、Compose UI 1.4+,以及相应库依赖。