1. 调试概述与 Compose 调试基础
说起调试,很多人的第一反应是:“Bug 来了,怎么办?” 其实在 Compose 里,调试不只是找 Bug,更是理解 UI 如何被渲染、重组、重绘。我个人的习惯是,拿到一个运行卡顿或布局异常的问题,先用工具跑一遍基础诊断,而不是直接看代码。咱们一步步来梳理。
1.1 为什么调试在 Compose 中尤为重要
Compose 是声明式 UI 框架,它把布局、绘制、动画都封装在重组(Recomposition)的周期里。一旦出现性能问题,往往不是单个方法慢,而是整个重组链条出了问题。举个例子:一个状态改变可能触发整个树的重组,这在传统 View 系统里是极少见的。
我在项目里遇到过这样的情况:一个简单的列表滚动,因为某个 ViewModel 的 liveData 频繁发射,导致整个 LazyColumn 的 Item 全部重组。用传统的 Log 去排查根本看不出哪里慢,直到我打开了 Layout Inspector 的 Compose 面板——嗯,真相一目了然。
1.2 调试工具链全景图
为了理清思路,我把常用的调试手段和工具画了一张结构图,方便对照。
1.3 基础调试手段速查表
| 调试目标 | 推荐工具/手段 | 关键指标 |
|---|---|---|
| 检查重组次数 | Layout Inspector + Compose 面板 | Recomposition count |
| 分析编译产物 | -P composeCompilerMetrics=true |
Stability(稳定性) |
| 定位 Layout 溢出 | Layout Inspector 3D 模式 | 边界矩形/溢出标记 |
| 性能火焰图 | Perfetto + Compose 跟踪 | Compose 阶段耗时 |
1.4 快速上手:开启 Compose 调试模式
先别急着一头扎进代码,你首先需要确保调试面板是活的。很多团队用了 Compose 但不知道 Android Studio 里有个专门的 Compose 调试入口。
// 在 build.gradle 中确保依赖
debugImplementation "androidx.compose.ui:ui-tooling:1.7.x"
debugImplementation "androidx.compose.ui:ui-test-manifest:1.7.x"
// 然后运行 app,在 Android Studio 中点击
// View → Tool Windows → Layout Inspector (新版叫 Layout Inspector with Compose)
打开后你会看到一个 3D 视角的组件树。还记得我前面提到的那个列表重组问题吗?就是在这棵树上看到了 Item 的 Recomposition Count 一直在增长,而其他 Item 的数据根本没变——当场破案。
1.5 理解 Compose 调试的核心概念
玩转调试工具之前,有几个概念你得心里有数。我整理成了一段简短的口诀:
- 重组(Recomposition):状态变化后,Compose 重新执行 @Composable 函数。调试时你看的就是它。
- 跳过(Skipping):如果参数没变化并且函数是稳定的,Compose 会跳过重组——这是性能优化的风向标。
- 稳定(Stability):一个数据类是否被标记为 stable 影响能否跳过。你可以在 Compiler Metrics 里查看。
- 副作用(SideEffect):LaunchedEffect、DisposableEffect、remember 这些都是调试的“警戒区”,容易导致意外触发。
1.6 我的调试前检查清单
在正式开始之前,我一般会花 3 分钟跑一遍下面的清单,少走很多弯路:
- 确认 Android Studio 版本 >= Hedgehog(新版工具链支持更好)
- 确认 debug build 包含 ui-tooling 和 ui-test-manifest
- 打开 Layout Inspector 并切换到 Compose 模式(别选错)
- 运行目标页面,点击几遍,看 Recomposition Counts 变化
- 如果卡顿严重,顺便记录一下 Compose 阶段的耗时(用 Perfetto)
嗯,这套流程救了我不下十次,你也可以试试。
1.7 小结
调试不是抓瞎,而是有策略地使用工具。Compose 提供的 Layout Inspector、Compiler Metrics、重组计数器都是你的眼睛。把它们组合起来,大多数性能或布局问题在半小时内就能定位。记住一个原则:先观测后改代码,别凭感觉乱加 remember。后面章节我们会深入每一个工具的实战用法——但今天先把基础打牢,足够了。