RecyclerView优化实操

320 阅读3分钟

DeepAndroid打算把这些年业务上做的东西好好总结下

github.com/loganpluo/D…

1、常规操作

(1)布局优化

  • 层次减少:merge、viewStub懒加载、减少多余层次(有其他文章说在item里面使用ConstraintLayout会有性能问题,目前我没碰到,可能高版本优化了)
  • view的个数减少: textview的span来替换、无用的view
  • view能确定大小尽量写死,避免measure:图片大小、item的高度
  • 避免过渡绘制: backgroud重叠可以去掉无用的
  • 减少inflater时间:方便代码写的布局可以替换xml(说是这么说,但是往往手写代码布局确实没有xml开发效率高,扩展和维护性好, goole出了个Jetpack Compose,后面看下原理,性能如何)

(2) cpu密集型操作 异步化

  • onBindViewHolder里面的数据直接用于展示, 避免有cpu密集型操作,例如:时间格式转化、解析表情、json解析等

(3)避免频繁new对象,消耗资源,触发gc可能频繁回收

例如 addXxListener根据 ID 来进行不同的操作,不要每次new XxListener

(4) 滚动过程中停止其他线程,避免和主线程竞争cpu资源

停止load图片(如果产品接受)

2、其他优化(之前我没做过的)

(1)diffUtil 的更新

diffUtil得用法,可以自己去网上搜,我的心得总结

  • 目前针对insert尾部添加数据和update 数据 确实性能比 全部notifydatachange更新渲染的帧率要好;
  • 但是在头部insert数据,diffutil触发的更新 有一些多余的刷新recyclerView操作,导致渲染的帧率并不好,这个地方还在 跟踪原因;
  • 另外diffUtil的计算最好放到异步线程,避免随着数据变多,计算变慢;

diffUtil确实提高刷新帧率,如果你想精细化到每个字段对应ui的diff变动,确实有一定开发成本,如下:

  • 你得手写字段是否相等逻辑,然后payloads里面读取 变化得字段 触发对应字段得ui刷新(这个过程后面我打算用字段反射和数据动态绑定来简化这个过程)
  • 新数据集合的对象得重新new一个,即使是一个字段值改变了(例如:你消息列表中,一个消息的状态变成发送成功了,你得重新new个新对象,然后把state改成成功,这样才能diff 新旧对象里面state字段值不一样,才会触发刷新stateView)

(2)扩大recyclerView的viewholder的缓存池,以空间换时间

例如在消息列表中, 文字和图片两种type的 viewholder使用最多,所以我就针对这两种type,扩大到10个,默认是5个

  RecyclerView.recycledViewPool.setMaxRecycledViews(int viewType, int max)

(3)如果是多个tab的形式,可以公用一个recyclerView的recycledViewPool缓存池,这样切tab可以更快

(4)性能更好的自定view组件

  • 自定义textview( 暂时没有做到,因为textview里面还嵌套了gif表情)

参考:
juejin.cn/post/684490…

github.com/SusionSuc/A…