compose中 SideEffect概念以及作用

SlideEffect排在第三位执行,一般是函数中最后一行同步代码执行完,再执行。

2025-12-26 14:22:10.974 6006-6006 Exp4 com.example.composestudy D 1️⃣ 函数体:data=初始

2025-12-26 14:22:10.974 6006-6006 Exp4 com.example.composestudy D 3️⃣ 函数体继续:data=初始

2025-12-26 14:22:10.980 6006-6006 Exp4 com.example.composestudy D 2️⃣ SideEffect 立即执行:data=初始

先给一个绝对准确的结论(可以直接记住)

SideEffect 的代码是在 Composable 函数执行"期间被记录",
但真正执行是在:本次重组完成、UI 变更已提交之后。

所以答案是:

  • 不是"函数最后一行执行完立刻执行"
  • 也不是"UI 已经绘制到屏幕之后"
  • "Compose 完成一次成功重组并提交变更之后,在同一帧内执行"

一、为什么日志"看起来像顺序执行"?(这是关键)

看到的是类似这种日志顺序,对吧 👇

kotlin 复制代码
@Composable
fun Demo() {
    Log.d("TAG", "A")

    SideEffect {
        Log.d("TAG", "SIDE")
    }

    Log.d("TAG", "B")
}

日志是:

text 复制代码
A
B
SIDE

或者有时会感觉:

"SideEffect 好像就是在函数里顺着跑的"

原因只有一个:

SideEffect 在函数执行时"被注册",不是立即执行

Compose 在函数执行阶段做的是:

text 复制代码
执行 Composable 函数
 ├─ Log("A")
 ├─ 注册一个 SideEffect(放进 effect 队列)
 ├─ Log("B")
函数执行结束

👉 此时 SideEffect 还没执行


二、真正的时间线(非常重要,给"底层级"顺序)

我们用一个真实的时序图来看一次重组:

text 复制代码
① 执行 Composable 函数(重组)
   ├─ 普通代码立即执行(Log、if、remember)
   ├─ SideEffect 只是被"登记"
   └─ UI 描述树被重新计算

② Compose 内部:
   ├─ 对比新旧 UI 树(diff)
   ├─ 确认这次重组是"成功的"
   └─ 提交 UI 变更(commit)

③ 执行 SideEffect(同步)

👉 SideEffect 永远在第③步


三、那为什么不是"UI 绘制完成之后"?(非常关键的区分)

Compose 有三层概念,很多人混在一起了:

层级 含义
重组(Recomposition) 重新计算 UI 描述
提交(Commit) 应用 UI 变更
绘制(Draw) 真正画到屏幕

SideEffect 的位置是:

text 复制代码
重组完成 ✅
提交完成 ✅
绘制开始 ❌ / 或正在同一帧调度中

SideEffect 不保证"画完了"

它保证的是:UI 状态已经稳定,不会被回滚


四、为什么 Compose 要这么设计?(设计动机)

核心原因一句话:

副作用是不可回滚的,而 UI 计算是可回滚的

如果:

  • UI 还在计算
  • 中途又被新的状态打断

👉 那这次 UI 计算会被丢弃

👉 但 SideEffect 如果已经执行,就会造成世界状态错乱

所以 Compose 的保证是:

只有当这次重组"确定要生效"时,才执行 SideEffect


五、再回答那句非常关键的直觉判断

"SideEffect 的执行似乎没有受到其他干扰"

这是对的,而且是刻意设计的

  • 它不会被中途 cancel
  • 不会被 recomposition 打断
  • 不受 key 控制
  • 只要这次重组提交了,就一定会执行一次

但注意 ⚠️:

每一次成功重组 → 执行一次 SideEffect


六、用一句"工程级"话术帮彻底定型

以后可以这样理解、这样跟别人说:

SideEffect 不是 Composable 代码的一部分,
而是"在这次 UI 更新已经确定之后,对外部世界做的同步动作"。


七、和 LaunchedEffect / DisposableEffect 的时序对比(加深理解)

API 注册时机 执行时机
SideEffect Composable 执行时 重组提交后(同步)
LaunchedEffect Composable 执行时 重组提交后(启动协程)
DisposableEffect Composable 执行时 进入 / 离开组合

八、现在已经到了 Compose 的「内核理解层」

能问出这个问题,说明已经在思考:

  • Compose 到底什么时候"算 UI"
  • 什么时候"影响世界"

这已经不是 API 层的问题了,是调度模型


二 示例

复制代码
@Composable
    fun ExperimentScreen4() {
        var data by remember { mutableStateOf("初始") }

        Log.d("Exp4", "1️⃣ 函数体:data=$data")

        // 同步 - 立即执行
        SideEffect {
            Log.d("Exp4", "2️⃣ SideEffect 立即执行:data=$data")
            data = "SideEffect 修改"  // 这行不会触发重组
        }

        // 异步 - 后台执行
        LaunchedEffect(Unit) {
            Log.d("Exp4", "4️⃣ LaunchedEffect 后台执行开始")
            delay(100)
            Log.d("Exp4", "5️⃣ LaunchedEffect 延迟后:data=$data")
        }

        Log.d("Exp4", "3️⃣ 函数体继续:data=$data")

        Text("当前数据:$data")
    }

2025-12-26 14:22:10.974  6006-6006  Exp4                    com.example.composestudy             D  1️⃣ 函数体:data=初始
2025-12-26 14:22:10.974  6006-6006  Exp4                    com.example.composestudy             D  3️⃣ 函数体继续:data=初始
2025-12-26 14:22:10.980  6006-6006  Exp4                    com.example.composestudy             D  2️⃣ SideEffect 立即执行:data=初始
2025-12-26 14:22:11.087  6006-6006  Exp4                    com.example.composestudy             D  4️⃣ LaunchedEffect 后台执行开始
2025-12-26 14:22:11.091  6006-6006  Exp4                    com.example.composestudy             D  1️⃣ 函数体:data=SideEffect 修改
2025-12-26 14:22:11.091  6006-6006  Exp4                    com.example.composestudy             D  3️⃣ 函数体继续:data=SideEffect 修改
2025-12-26 14:22:11.095  6006-6006  Exp4                    com.example.composestudy             D  2️⃣ SideEffect 立即执行:data=SideEffect 修改
2025-12-26 14:22:11.188  6006-6006  Exp4                    com.example.composestudy             D  5️⃣ LaunchedEffect 延迟后:data=SideEffect 修改
相关推荐
码农搬砖_20204 小时前
【一站式学会compose】 Android UI体系之 Text的使用和介绍
android·compose
stevenzqzq21 小时前
Compose基础入门
开发语言·compose
stevenzqzq1 天前
Compose 实战练习
compose
遇见火星4 天前
Docker Compose 实战教程,理解Docker Compose核心概念,学会编写 compose.yml,掌握常用命令!
运维·docker·容器·compose
csdn12259873368 天前
JetPack Compose 入门先搞清楚
android·compose·jetpack
モンキー・D・小菜鸡儿16 天前
Android Jetpack Compose 基础控件介绍
android·kotlin·android jetpack·compose
hnlgzb1 个月前
androidx.compose.material3哪几个文件是经常用到的?
androidx·compose
drsonxu1 个月前
Android开发自学笔记 --- 构建简单的UI视图
android·compose