闲鱼在业务快速发展时,APP长列表滑动流畅度逐渐变差,严重影响了用户浏览体验。而当下又缺乏理想的检测工具,接下来让我们一起看看闲鱼是怎么一步步试图解决这个难题。
Total frames rendered: 2245
Janky frames: 31 (1.38%)
50th percentile: 5ms
90th percentile: 10ms
95th percentile: 14ms
99th percentile: 18ms
卡顿问题凸显
随着闲鱼业务不断快速迭代,APP长列表滑动流畅度情况日益让人头疼。用户在使用时,经常会遇到滑动卡顿延迟的现象。统计显示,在部分机型上卡顿发生率能达到 30%,这样的情况严重伤害了用户浏览内容的体验,也极大降低了用户对平台的好感度。
点击:adb shell input tap $x $y
滑动:adb shell input swipe $x1 $y1 $x2 $y2 $duration
检测工具困境
目前市场上没有一款无侵入的流畅度检测工具可以同时支持多平台、多机型与多指标数据。侵入式检测工具虽可对自身 APP 进行检测,但不能检测竞品 APP。比如想了解其他同类平台的流畅度时,现有的工具就没办法派上用场,导致很难进行对比优化。
卡顿原理揭秘
APP 列表滑动其实是按照一定频率(60hz 下 16.6ms)和不同偏移量计算出一系列静止画面,以此产生滑动动画的视觉效果。依据这个原理,如果得到 APP 滑动过程的录屏数据,通过每 16.6ms 检测录屏画面是否有变化,若连续画面未变就表明出现了卡顿,这为卡顿检测提供了理论基础。
录屏数据获取
为获取目标 APP 的录屏数据,利用检测工具 APP 向系统注册录屏服务。之后在检测工具 APP 的帧回调里持续读取录屏画面,并且将其和上次检测画面的 hash 值做比对。以闲鱼 APP 为例,成功获取到了滑动过程中的录屏数据,为后续的流畅度检测奠定了数据基础。
优化方向探寻
查看闲鱼首页显示和初始滑动流程,能发现流程中的其他 UI 操作和等待用户操作环节都存在优化的空间。起初考虑定义视图数据层,把 UI 和非 UI 操作分开,不过实际编码时发现,业务代码改动量太大且容易出错,AB 测试逻辑也很难实现,方案推行起来困难重重。
性能优化实践
进行性能优化前,得先了解 flutter 的渲染原理,像 Widget、Element、RenderObject 三棵树结构,Widget 到屏幕显示的流程等。由于闲鱼业务里列表 item Widget 结构相近,所以通过根据类型复用 element,成功把一个超大 widget 构建从 1 帧时间分散到 4 帧时间内完成。分帧上屏大多在不可见的 Cache 区域完成,在高端机或正常滑动时用户几乎察觉不到差异,优化了卡顿问题。
// reducer.dart
// 滑动事件监听
static BottomBarState onScroll(BottomBarState state, Action action) {
...
return state.clone()..scrollPercent = scrollPercent;
...
}
完成优化后的数据表现良好,但实际体验上 Flutter 页面还是有卡顿感。大家觉得是优化方向出了问题,还是检测指标不够完善导致的?欢迎点赞分享文章并留言评论。
11-15 15:03:43.684 27076 27271 I flutter : CommonBuyDetailPage performance: ItemBodyAction.onScrollBroadcast 261
11-15 15:03:43.701 27076 27271 I flutter : CommonBuyDetailPage performance: ItemBodyAction.onScrollBroadcast 1933
11-15 15:03:43.716 27076 27271 I flutter : CommonBuyDetailPage performance: ItemBodyAction.onScrollBroadcast 371