yunshuipiao/Potato

Android RecyclerView Optimization

Opened this issue · 1 comments

Android RecyclerView Optimization

[TOC]

这篇文章总结一下 RecyclerView 的优化使用

数据处理和视图加载分析

在拿到数据之后,其处理也应该异步操作。最后将直接要显示的结果进行显示。

数据优化

分页拉取远端数据,对取下来的远端数据进行缓存,提升二次加载速度;

对于新增或者删除数据,通过 DiffUtil 进行局部计算更新,而不是全局更新。

布局优化

减少过渡绘制

减少 VH 中的布局层级,可以考虑自定义 View 或者更合理的较少布局层次,不推荐使用

ConstraintLayout。

减少 xml 文件的 inflate 时间

这里的 xml 文件不仅包括 layout 的 xml,还包括 drawable 的 xml,xml 文件 inflate 出 ItemView 是通过耗时的 IO 操作,尤其当 Item 的复用几率很低的情况下,随着 Type 的增多,这种 inflate 带来的损耗是相当大的,此时我们可以用代码去生成布局,即 new View() 的方式,只要搞清楚 xml 中每个节点的属性对应的 API 即可。

减少 View 对象的创建

一个稍微复杂的 Item 会包含大量的 View,而大量的 View 的创建也会消耗大量时间,所以要尽可能简化 ItemView;设计 ItemType 时,对多 ViewType 能够共用的部分尽量设计成自定义 View,减少 View 的构造和嵌套。

其他

  • 升级 RecycleView 版本到 25.1.0 及以上使用 Prefetch 功能,可参考 RecyclerView 数据预取
  • 如果 item 高度固定,可以使用 setHasFixedSized(true), 来避免 requestLayout 浪费资源。
  • 设置 addOnScrollListener(), 对滑动过程中停止加载的操作,比如图片等
  • 可以考虑关闭默认动画
  • 重写 onViewRecycled() 来回收资源
  • 使用 setItemViewCacheSize() 来加大 RecyclerView 的缓存,空间换时间来提高滚动的流畅性。
  • 如果多个 RecyclerView 的 Adapter 一致,可以通过设置 setRecyclerdViewPool(),来共用一个 RecyclerViewPool。
  • 对 VH 中设置监听器时,不要对每个 item 都调用 addListener。应该公用一个监听器,根据 ID 来进行不同的操作,优化对象频繁创建带来的资源损耗。

复用和缓存策略

一般说的 RecyclerView 中有四级或者三级缓存,都是有 Recycler 类来控制。

public final class Recycler {
    final ArrayList<ViewHolder> mAttachedScrap = new ArrayList<>();
    ArrayList<ViewHolder> mChangedScrap = null;

    final ArrayList<ViewHolder> mCachedViews = new ArrayList<ViewHolder>();

    private final List<ViewHolder>
            mUnmodifiableAttachedScrap = Collections.unmodifiableList(mAttachedScrap);

    private int mRequestedCacheMax = DEFAULT_CACHE_SIZE;
    int mViewCacheMax = DEFAULT_CACHE_SIZE;

    RecycledViewPool mRecyclerPool;

    private ViewCacheExtension mViewCacheExtension;
  ...
}

Recycler是负责管理成为碎片的视图或者已经detached的视图,从而实现View的复用。

RecycledViewPool可以让你在多个RecyclerView之间分享视图.

ViewHolder的创建和bind都是由Recycler执行的。还有LayoutManager获得ViewHolder的itemView,也是通过Recycler提供的。简单介绍一下Recycler和RecyclerViewPool的内部结构:

  • Recycler里有几个ViewHolder的容器,用来存储不同状态的ViewHolder,以便之后复用。其中ViewCacheExtension类,是用户可以自定义复用机制的类。

  • RecyclerViewPool,这个可以从外部对多个RecyclerView设置同一个RecyclerViewPool,从而实现多个RecyclerView中的ViewHolder的复用。