1. Compose 调试概述与工具链

刚接触 Compose 调试时,很多人会问:到底该从哪开始?坦白讲,我也迷茫过一阵子。Compose 是声明式 UI,运行时状态全靠重组——出问题了你不能像 View 系统那样直接看「某个 View 的宽高」,得换一套思路。

这一节我们不写代码,先把手里的家伙摸清楚。我习惯把调试工具分成三类:布局看诊器、日志捕手、性能探测器。它们分别对应 Layout Inspector、Logcat 和 Profile。下面一个个说。

1.1 Layout Inspector——布局的「X光机」

Layout Inspector 这东西,说白了就是把你屏幕上的 Compose 组件树拍成一张「解剖图」。你可以选某个节点,右边直接看到它的属性、修饰符、重组次数。

我项目里遇到过一个奇怪问题:Text 组件显示的文字明明对,但位置偏了 2 像素。用 Layout Inspector 一看,原来外层多了个 Modifier.padding(2.dp)——当时开发合并代码时冲突没解干净。如果没有这「X光机」,你光靠眼瞪屏幕,很难找到那 2 像素的坑。

使用技巧:在 Layout Inspector 窗口顶部的搜索框里输入 composable,可以快速过滤出所有 Compose 节点。我一般先搜「recompose」看哪些组件频繁重组。

打开方式:Tools → Layout Inspector → 选择进程 → 开始检查。嗯,这里要注意:如果你同时开了多个模拟器,进程列表会很长,建议按包名排序。

1.2 Logcat——聊天的录音笔

前面提到 Layout Inspector 是静态抓图,那 Logcat 就是动态的「聊天记录」。你可以在代码里加 Log.d("TAG", "某个重组时机"),然后看着日志流判断状态是否正确更新。

我个人习惯给每个 Compose 函数设一个唯一的 TAG,比如 "HomeScreen_Composable"。有一次排查列表项闪烁的 bug,就是靠 Logcat 里看到 LaunchedEffect 被多次调用,才发现 key 设置错了。

// 常用调试日志写法
@Composable
fun MyItem(item: Item) {
    Log.d("MyItem", "重组了, item.id = ${item.id}")
    Text(text = item.name)
}

顺便提一嘴:Logcat 的过滤栏里可以用 package:mine 只看当前应用日志,再用 tag:MyItem 缩小范围,这俩组合是我最常用的。

踩坑提醒:我曾经在生产包上忘记删除调试日志,导致 Logcat 疯狂输出,拖慢 UI 线程。建议用 BuildConfig.DEBUG 包一下日志代码,release 时自动去掉。

1.3 Profile——性能的侦探器

Profile 工具可以记录 CPU、内存、网络、以及 Compose 特有的 重组次数 和 Compose 阶段耗时。我个人最常用的是「Record & Profile」,运行一小段操作,然后看火焰图。

你知道 Compose 的 UI 构建分三个阶段吗?组合 → 布局 → 绘制。如果在火焰图里看到「Layout」阶段特别长,多半是某个 Modifier 或 Layout 自定测量搞了复杂计算。我优化过一个卡片滑动卡顿的问题,就是靠 Profile 定位到 Modifier.shadow 在每次重组都重新计算阴影路径——换成预置的 Elevation 直接降了 30% 耗时。

关键指标:关注 Recomposition count 是否超过预期。一个典型的列表项如果在滑动时每帧都重组,那肯定有问题。正常情况应该只有需要更新的项才重组。

打开方式:View → Tool Windows → Profiler → 选择设备 → 选择 Compose 选项卡(如果有)或直接看 CPU。

1.4 一张图串起三个工具

下面这张图是 Compose 调试工具链的协作逻辑:发现 bug → 用哪个工具 → 怎么定位。我个人觉得这张图能帮你形成「调试直觉」。

Compose 调试工具链协作流程 遇到 UI 问题 布局错位/样式异常 状态更新/数据显示 卡顿/过度重组 Layout Inspector Logcat Profiler 查看组件树、属性、修饰符 过滤 TAG、定位重组时机 记录操作、分析火焰图 交叉验证:Layout Inspector + Logcat + Profiler

1.5 一张比较表帮你快速决策

工具 擅长场景 不擅长的场景 我常用的启动方式
Layout Inspector 组件层级、修饰符、属性值 无法捕捉动画过程中的中间态 Tools → Layout Inspector
Logcat 状态变化、事件触发顺序 定位性能瓶颈(缺少时间戳分析) 底部 Logcat 窗口直接查看
Profiler 重组次数、阶段耗时、内存泄漏 不能直接看到 UI 的视觉表现 View → Tool Windows → Profiler

1.6 小结:先有工具思维,再下手调试

你看,这三个工具其实覆盖了 Compose 调试的三种典型链路:看结构 → 看日志 → 看性能。我个人经验是,先判断你的问题属于哪一类,然后直奔对应的工具。如果交叉验证后依然找不出原因,就把三个工具的结果放在一块对比——这招帮我至少解决过 3 个线上疑难杂症。