
它们两个的执行先后顺序并不是由它们在文件代码里的编写顺序决定的。无论是把 LaunchedEffect 写在前面还是把 DisposableEffect 写在前面它们的底层执行阶段不同。1. 结论DisposableEffect 永远比 LaunchedEffect 先执行在 Compose 的生命周期底层渲染管线中两者的执行时机有严格的先后顺序第一步页面重组Recomposition→\rightarrow→运行函数体代码收集所有 Effect。第二步界面布局与绘制Layout Draw→\rightarrow→确定 UI 尺寸并画在屏幕上。第三步触发 DisposableEffect同步执行→\rightarrow→它最先被触发。第四步触发 LaunchedEffect异步挂起→\rightarrow→它最后被触发。2. 为什么 DisposableEffect 永远跑在前面底层原理这两者的定位和设计初衷完全不同导致了它们执行速度的差异 跑得快的 DisposableEffect定位它是同步执行的。原因它通常用来注册广播、挂载核心回调比如车机信号、生命周期观察者。这类注册逻辑必须在 UI 刚刚挂载完的瞬间立刻、马上、没有延迟地生效否则可能会漏掉紧接着发生的系统通知。所以它享有最高优先级的执行权。 跑得慢的 LaunchedEffect定位它是异步的基于协程。原因它内部通常用来跑耗时任务比如 delay()、网络请求、加载数据库等。Compose 为了不让这些耗时或异步任务卡住主线程的 UI 渲染会故意把 LaunchedEffect 放到整个渲染周期的最后一步或者是下一帧进入协程作用域去异步调度执行。3. 日志实测验证我们可以写一段测试代码故意把 LaunchedEffect 放在文件最上面把 DisposableEffect 压在最下面Composablefun TestScreen() {// 故意写在第一行LaunchedEffect(Unit) {Log.i(“EffectOrder”, “【LaunchedEffect】执行了异步协程”)}// 故意写在最后一行 DisposableEffect(Unit) { Log.i(EffectOrder, 【DisposableEffect】主体执行了同步挂载) onDispose { } }} Logcat 真实的打印结果14:00:00.001 QQMusic I 【DisposableEffect】主体执行了同步挂载14:00:00.003 QQMusic I 【LaunchedEffect】执行了异步协程可以看到即使你在代码里把 LaunchedEffect 写在最前头最终打印出来的结果依然是 DisposableEffect 稳稳地跑在前面。 行业避坑总结如果有强依赖的先后顺序千万不要寄希望于通过“调整代码的上下行顺序”来控制它们的先后。黄金法则如果是注册、挂载、建立同步连接的逻辑一律放进 DisposableEffect。如果是网络请求、定时器、耗时动画、协程异步流一律放进 LaunchedEffect。