RecyclerView 卡顿排查的几个套路

最近接手了一个商品列表页,产品反馈"滑动的时候有一点点卡,但说不清楚哪里卡"。这种模糊的需求最难办,记录一下我的排查过程,下次遇到可以直接翻这篇。 第一步永远是先量化,不要靠手感。 打开开发者选项里的 GPU 渲染模式,或者直接接 Systrace 看帧耗时。我们的情况是滚动时偶发 30ms+ 的帧,但不是每一帧都卡。这种偶发型卡顿,onCreateViewHolder 的嫌疑最大。 然后按嫌疑大小逐个排除: onBindViewHolder 里有没有做 IO?我们的问题就出在这——图片文案里的表情包配置是从 SharedPreferences 同步读的,第一次滚动到该位置时阻塞了主线程。改成启动时预加载到内存就好了。 item 布局层级是否太深。用 Layout Inspector 看了下,我们最深的一层嵌套了 7 层,把多余的 LinearLayout 换成 ConstraintLayout 之后测量耗时明显下降。 setHasFixedSize(true) 加了吗?数据变化不改变 item 高度的话,加上能省一次全量布局。 DiffUtil 用了没?我们还在用 notifyDataSetChanged(),全量刷新导致大量无意义重绘,换成 DiffUtil 后滑动顺滑了一个档次。 最后一个不算套路的心得:别过早优化。上面这些做完之后帧耗时稳定在 16ms 以内了,我本来还想上 RecyclerView 的 prefetch 调参,试了下收益几乎为零,就回滚了。性能优化到"感知不到卡"就该停手,剩下的时间是业务的时间。

2018-11-06 · 芮靖安