第一章 卡顿现象分类与表象识别
界面卡顿从来不是单一症状。不同的底层原因会表现为截然不同的用户感知。只有准确将用户反馈归类到掉帧、冻屏、逐帧慢、触摸延迟四类现象,才能进入后续的数据采集与根因分析。本章聚焦每种现象的外部表现与用户感受,并给出快速分类的故障树与判断规则。
四种卡顿现象对照表
| 现象 | 外部表现 | 用户感知 | 典型触发场景 |
|---|---|---|---|
| 掉帧(Jank) | 帧率曲线出现间歇性低谷(如从 60 fps 骤降至 10 fps) | 画面突然跳跃、不连贯,滚动或动画时尤其明显 | 快速滑动列表加载大图、首次进入复杂 Compose 布局 |
| 冻屏(Freeze) | 画面长时间(>200 ms)无任何更新,触摸无响应 | 应用“死”掉了,卡住不动,用户频繁点击或等待 | 主线程同步 I/O、大量 Modifier 重组导致 UI 线程阻塞 |
| 逐帧慢(Slow Frame) | 每帧渲染时间稳定超出 16 ms(如 33 ms),帧率降至 30 fps 以下 | 动画缓慢、拖动不流畅,但无跳跃感 | 过度绘制、复杂自定义 Layout 测量耗时 |
| 触摸延迟(Touch Delay) | 触摸事件到界面响应的时间明显增加(>100 ms) | 点击感觉“粘滞”、拖拽跟手性差、游戏操作滞后 | 输入事件处理链路过长、Compose 手势 Modifier 递归 |
卡顿现象故障树
下图从“界面卡顿”根节点出发,根据核心症状区分四种现象,并标注每种现象带给用户的最直接感受。故障树可帮助你在接到问题反馈后,30 秒内将问题归类。
现象识别判断规则
将用户抱怨 “卡” 映射到具体类别时,可参考以下量化规则(单位:ms):
- 掉帧:在 Choreographer 帧时间记录中出现单个帧 > 16 ms 且前后帧时间相差 > 10 ms,波动呈脉冲状。
- 冻屏:连续 3 帧以上帧时间 > 100 ms,且 UI 线程无其他事件处理(可通过 dumpsys gfxinfo 查看)。
- 逐帧慢:平均帧时间 > 16 ms,但标准差较小(< 5 ms),帧率稳定在较低水平。
- 触摸延迟:输入事件从硬件产生到 Compose 手势开始处理的时间 > 50 ms(可通过 system trace 中 Input 阶段与 Render 阶段的间隔判断)。
排查数据采集建议
快速采集帧时间曲线
在 Compose 代码中直接嵌入
在 Compose 代码中直接嵌入
Modifier.drawWithContent 测量帧耗时,或使用 Android Studio 的 Profile GPU Rendering 功能:adb shell dumpsys gfxinfo <package> framestats
输出结果中逐帧展示 FRAME_COMPLETED 的时间,即可识别掉帧 vs 逐帧慢。
常见混淆点
“掉帧”和“逐帧慢”容易混淆:掉帧是间歇性冲击,恢复后帧率立刻回正常;逐帧慢是持续性低帧率,每一帧都慢。查看帧时间分布曲线的离散程度即可快速区分。
“掉帧”和“逐帧慢”容易混淆:掉帧是间歇性冲击,恢复后帧率立刻回正常;逐帧慢是持续性低帧率,每一帧都慢。查看帧时间分布曲线的离散程度即可快速区分。