流畅度分析

当滑动发生时,系统会以固定节奏尝试绘制下一帧;任何一次绘制间隔明显拉长,用户都会感知为“卡了一下”或“抖动”。这些瞬时的长帧就是“丢帧”的来源。滑动场景对节奏变化最敏感,因为视觉上背景、文本与图片在持续位移,一旦节拍不稳,人眼会立即察觉。

线下 Trace 分析

线下 Trace 的目标是:还原滑动交互的帧时序,把“哪一段丢帧”与“为何丢帧”连接起来,给出直接可改的点位。Trace 的抓取请参考 录制 Trace,注意确保覆盖滑动交互的完整时间窗以及页面滑动速度。

Trace 展示丢帧原理

在 Trace 网页中的 Choreographer#doFrame 执行起点处增加了帧渲染耗时标签(目前仅支持 Android 端)。这些标签用于显示整个系统渲染过程中的丢帧情况,通过观察这些标签可以直观识别渲染过程中的渲染耗时异常。帧的渲染耗时是通过累加 UI 线程中的 Choreographer#doFrameRenderThread 线程中的 DrawFrames 的耗时来计算的。如果总耗时大于或等于 32 毫秒,标签将显示为红色;如果总耗时大于或等于 16 毫秒且小于 32 毫秒,标签显示为橘黄色;如果总耗时小于 16 毫秒,标签则为绿色。线下分析时我们可以认为红色标签和黄色标签对应的任务是导致丢帧的任务重点分析。

Frame Rendering Time

在滑动期间定位丢帧段

  • 在时间线中查找明显超出节拍的帧(例如连续出现红色标签),标记为“长帧片段”。
  • 逐帧分析,确认到底是主线程拥塞、渲染提交延迟,还是资源加载解码插入了关键路径。
  • 将长帧片段与界面元素对应起来(例如大图、复杂列表项、卡片动画),形成“可落地”的关联。

根因模式与识别方法

  • 主线程阻塞:布局与测量成簇叠加,或存在 I/O 操作在 UI 线程执行。
  • 布局与绘制过重:深层级、频繁重排或大面积重绘;文本与图片尺寸计算集中;Canvas 绘制复杂。症状是单帧计算时间异常拉长,且随滚动重复出现。
  • 图片与资源加载:解码、下采样、纹理上传卡在关键帧;异步没真正隔离,或未使用占位与预加载。表现为 GPURenderThread 队列积压,与图片尺寸或数量相关。

常见排查建议

  • 减少主线程工作量:把非必须计算与 I/O 移出 UI 线程;分帧化布局与绘制,避免“所有工作挤在一帧”。
  • 优化布局层级与测量:控制深度与约束复杂度;避免重复测量;使用合成层减少不必要的重绘。
  • 图片与资源治理:限制尺寸与体积,使用占位与预加载;解码与纹理上传尽量前移或并行;按需加载与缓存复用。
  • JS 与 Bridge:切分长任务,减少同步调用;使用节流与批处理,避免高频消息压迫 UI 节奏。
除非另有说明,本项目采用知识共享署名 4.0 国际许可协议进行许可,代码示例采用 Apache License 2.0 许可协议进行许可。