jetpack compose 副作用 SideEffect

SideEffect 用于将 Compose 内部状态安全地同步到外部非 Compose 世界。执行时机Composition 成功提交后、下一次重组之前。如果组合失败,SideEffect 不会执行。

场景 1:将 Compose 状态同步到外部对象

复制代码
@Composable
fun ChatScreen(viewModel: ChatViewModel) {
    val messages by viewModel.messages.collectAsState()
    val listState = rememberLazyListState()
    
    SideEffect {
        // 把滚动位置同步给 ViewModel 做持久化
        viewModel.saveScrollPosition(listState.firstVisibleItemIndex)
    }
}

场景 2:分析埋点

复制代码
@Composable
fun ProductPage(product: Product, tracker: AnalyticsTracker) {
    SideEffect {
        tracker.logEvent("product_view", mapOf("id" to product.id))
    }
}

注意事项

1、不要在 SideEffect 里修改 Compose State --- 会导致无限重组循环

2、适合"读"操作,不适合"写"操作 --- 它是同步出去,不是触发变化

3、如果需要异步操作,用 LaunchedEffect 而不是 SideEffect

源码

复制代码
// 1. SideEffect.kt 
@Composable
fun SideEffect(effect: () -> Unit) {
    currentComposer.recordSideEffect(effect)
}

和 snapshotFlow 的对比

对比项 SideEffect snapshotFlow
登记方式 recordSideEffect() → changes 列表 Snapshot.registerApplyObserver()
执行时机 Composition commit 成功 Global Snapshot apply 成功
失败处理 组合失败 → 丢弃 Snapshot apply 成功才回调
底层共同点 都依赖"记录→提交"模式,不是立即执行 都依赖"记录→提交"模式,不是立即执行

Snapshot 状态管理层 和 Composer UI 构建层

复制代码
Composition 层 (构建 UI 树)
    │
    │  依赖
    ▼
Snapshot 层 (管理状态读写)

Snapshot apply 发生在底层,Composition commit 发生在上层。一个改了状态值,一个改了 UI 树。

Snapshot apply 只是把数据标记为已确认,但 UI 树不一定刷新:

复制代码
// 场景:快速连续点击
button.onClick {
    count++  // → 触发 Snapshot apply(数据层)
    count++  // → 又触发一次 Snapshot apply
}
// 但 Composition 只会在下一帧跑一次重组
// → 两次 Snapshot apply,一次 Composition commit
对比项 Snapshot apply Composition commit
改了啥 State 值(变量层面) UI 节点树(LayoutNode 层面)
所在的层 Snapshot 系统 Composer 系统
触发者 MutableSnapshot.apply() 帧回调 + Composer
失败怎么办 几乎不会失败(纯数据合并) 可能失败(异常/中断 → 丢弃整棵树)
观察者 registerApplyObserver recordSideEffect
典型案例 snapshotFlow 在此回调 SideEffect 在此回调
相关推荐
_祝你今天愉快5 小时前
从驱动来分析服务的添加过程
android
Dovis(誓平步青云)8 小时前
折叠屏悬停看视频,上半屏和下半屏应该各做什么
android·java·服务器·开发语言·安全·音视频
alexhilton9 小时前
让架构边界变成可执行的测试
android·kotlin·android jetpack
hai_android10 小时前
SendChannel 与 ReceiveChannel 通信机制
android
数据治理自习室12 小时前
AI 应用评测体系(GraphRAG)
android·大数据·人工智能·kotlin
爱笑鱼13 小时前
Android 系统启动机制(五):system_server 是 init 启动的,还是 Zygote fork 出来的?
android
智购科技无人售货机工厂14 小时前
2026自动售货机防拆机物理安全设计:从安全螺丝到结构互锁的工程实践~YH
android·网络·驱动开发·python·单片机·安全·云原生
开开心心就好14 小时前
电子教鞭工具支持画框写字插图片功能齐全
android·开发语言·前端·javascript·人工智能·pdf·html
Dovis(誓平步青云)14 小时前
拍视频前先把镜头想清楚:做一个分镜取景辅助器
android·java·服务器·javascript·人工智能
峥嵘life15 小时前
Android16 系统 APEX 模块说明
android·大数据·开发语言