Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Android RecyclerView Optimization #45

Open
yunshuipiao opened this issue May 26, 2019 · 1 comment
Open

Android RecyclerView Optimization #45

yunshuipiao opened this issue May 26, 2019 · 1 comment
Labels

Comments

@yunshuipiao
Copy link
Owner

yunshuipiao commented May 26, 2019

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的复用。

@yunshuipiao
Copy link
Owner Author

yunshuipiao commented Feb 9, 2020

@yunshuipiao yunshuipiao pinned this issue Feb 9, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant