RecyclerView与ListView

RecyclerView简介

RecyclerView组件:

图片来源于网络

各部件关系如图:

图片来源于网络

RecyclerView 本质是ViewGroup,它通过 LayoutManager 来控制其 ItemView 的布局,也通过ItemAnimator来控制 ItemView 添加和删除动画。LayoutManager 仅控制 ItemView 的布局,并不控制 ItemView 的创建、缓存和回收,它会将该工作委托给 Recycler 进行。Recycler 本质就是 ItemView 的多级缓存,它仅控制 ItemView 的缓存和回收,也不负责 ItemView 的创建和数据绑定,它从 Adapter 里获取已经绑定好数据的 ItemView,以 ViewHolder 的形式;Adapter 负责数据源的访问,和生成新 ItemView,并将其绑定好数据,供 Recycler 获取。

DiffUtil 与局部刷新

DiffUtil 是配合 RecyclerView 使用的工具类,通过比较新旧数据源的差异,生成旧数据源到新数据源的最小改动,然后对有改动的 ItemView 进行局部刷新。DiffUtil 内部采用 Myers' diff 算法(迈尔斯差分算法)进行比较,git 也是采用的这个算法。

Recycler 的四级缓存

  • 一级缓存 Scrap,变量 mAttachedScrap、mChangedScrap,不需要重新 bindView;

       最高优先级的缓存,用来保存被 RecyclerView 移除掉,但最近又马上要使用的缓存。

       mAttachedScrap 存储的是当前还在屏幕中的 ViewHolder,比如,RecyclerView 滑出一个新的 ItemView,此时会重新调用 LayoutManager 的 onLayoutChildren 方法,从而会将屏幕上所有的 ViewHolder 先 scrap 掉(废弃掉),添加到 mAttachedScrap 里面去,然后在重新布局每个 ItemView时,会从优先 mAttachedScrap 里面获取。这样 scrap 缓存里的 ItemView(即当前界面中的 ItemView)就可以不用重新绑定数据,直接拿来用就可以了,仅需要绑定新进入界面的 ItemView(如果该 ItemView 来自CachedViews 缓存,也不需要重新绑定)。

       mChangedScrap 存储的是数据被更新的 ViewHolder,比如,调用了 Adapter 的 notifyItemChanged 方法。

  • 二级缓存 CachedViews,变量 mCachedViews,不需要重新 bindView;

       默认大小为2,通常用来存储预取的 ViewHolder,同时在回收 ViewHolder 时,也会可能存储一部分的 ViewHolder

  • 三级缓存 ViewCacheExtension,变量 mViewCacheExtension;

       用户自定义缓存

  • 四级缓存 RecyclerViewPool,变量 mRecyclerPool,需要重新 bindView;

       ViewHolder 缓存池,根据 ViewType 来缓存 ViewHolder,每个 ViewType 的数组大小为5,可以动态的改变。

图片来源于网络

 

RecyclerView与ListView比较

  1. 缓存上来说(Recycler),RecyclerView 拥有四级缓存,ListView 只有两级。两者缓存机制上基本一致,但 RecyclerView 提供了数据源改变时的局部刷新能力,ListView只能一锅端。而且 RecyclerView 在特定场景下对 ListView 的缓存机制做了补强和完善。其次,缓存内容上,RecyclerView 缓存 ViewHolder,ListView 缓存 View;
  2. 适配器上来说(Adapter),RecyclerView 内置了ViewHolder,避免重复 findViewById,ListView 只有自己手动实现;
  3. 效果增强方面(ItemDecoration、ItemAnimator),RecyclerView 可以通过 ItemAnimator 自定义数据变化时 ItemView 的动画效果,通过 ItemDecoration 绘制 ItemView 之间的UI(分割效果);
  4. 布局样式上来说(LayoutManager),RecyclerView 有 LayoutManager 支持水平、网格、瀑布流等布局;

    

 

RecyclerView性能优化

  • 数据集优化:
  1. 分页加载远端数据,对拉取的远端数据进行缓存,提高二次加载速度;
  2. 新增、删除数据时,通过 DiffUtil 来进行局部数据刷新;
  3. 数据处理和视图加载分离,对于数据集的一些耗性能处理,不应该放到 onBindViewHolder 里,应该在更新数据集时处理好,避免每次 onBindViewHolder 都去处理;
  • 布局优化:
  1. 通过合理布局和自定义View,来减少布局层级;
  2. xml 文件 inflate 出 ItemView 是IO操作,可以通过Java代码来代替 xml 布局,提高性能(性能要求高时使用,太复杂);
  3. 固定 ItemView 的宽或高(取决于你的 List 是横还是竖),尽量不要 wrap_content 或用 weight 去配比例,避免去 requestLayout;
  • 缓存优化:
  1. 加大 RecyclerView 的缓存;
  2. 增加 RecyclerView 预留空间,在显示范围之外,RecyclerView有额外的空间可以放 ItemView;
  3. RecyclerView 数据预取(21版本以上);
  4. 嵌套的 RecyclerView 中,子 RecyclerView 有相同的 adapter,可以共用一个 RecycledViewPool;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值