IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> RecyclerView(三)—— RecyclerView的缓存机制 -> 正文阅读

[移动开发]RecyclerView(三)—— RecyclerView的缓存机制

Recyclerview的缓存机制

recycler [ri:'saikl?] 反复循环器,[化工] 再循环器

Android新增的Recyclerview主要用于代替ListViewRecyclerview可扩展性强。

  • 可以通过LayoutManager形成线性(横向与竖向)、网格、瀑布流布局。
  • 通过OnItemTouchListener监听Item的事件,虽然比ListView.OnItemClickListener麻烦了点,但是可以实现更复杂的功能,比如item滑动。
  • 提供了notifyItemInsertednotifyItemRemovednotifyItemChangednotifyItemMoved来提高局部刷新的效率。
  • 没有ListViewHeaderViewFooterView , 但可以通过来getItemViewType来生成不同的视图。
  • RecyclerView还定义了ViewHolder,配合RecyclerView.Adapter,封装重用ItemView的逻辑,还有四级缓存,效率大大增加。

1 Recyclerview的缓存类

RecyclerView缓存基本上是通过三个内部类管理的,RecyclerRecycledViewPoolViewCacheExtension

extension [?k?sten?n] 延伸,扩展

1.1 Recycler

用于管理已经废弃或者与RecyclerView分离的ViewHolder,以下是内部类的成员变量和它们的含义:

Recycler的成员变量

Scrap缓存用在RecyclerView布局时,布局完成之后就会清空

添加到Cache缓存和RecyclerViewPool缓存的item,它们的View必须已经从RecyclerViewdetachedremoved

scrap [skr?p] 碎片,小块; attach [??t?t?] 系上,贴上 detached [d??t?t?t] 单独的,分离的

public class RecyclerView extends ViewGroup implements ScrollingView,
		NestedScrollingChild2, NestedScrollingChild3 {

  public final class Recycler {
    final ArrayList<ViewHolder> mAttachedScrap = new ArrayList<>();
    ArrayList<ViewHolder> mChangedScrap = null;
   
    final ArrayList<ViewHolder> mCachedViews = new ArrayList<ViewHolder>();
    
    private ViewCacheExtension mViewCacheExtension;
    
    RecycledViewPool mRecyclerPool;

    int mViewCacheMax = DEFAULT_CACHE_SIZE;
    static final int DEFAULT_CACHE_SIZE = 2;
  }
}

1.2 RecycledViewPool

RecycledViewPool类是用来缓存Item用,是一个ViewHolder的缓存池,如果多个RecyclerView之间用setRecycledViewPool(RecycledViewPool)设置同一个RecycledViewPool,它们就可以共享Item。其实RecycledViewPool的内部维护了一个Map,里面以不同的viewTypeKey存储了各自对应的ViewHolder集合。 可以通过提供的方法来修改内部缓存的Viewholder

public class RecyclerView extends ViewGroup implements ScrollingView,
		NestedScrollingChild2, NestedScrollingChild3 {

  public static class RecycledViewPool {
    private static final int DEFAULT_MAX_SCRAP = 5;
  }

}

1.3 ViewCacheExtension

开发者可自定义的一层缓存,是虚拟类ViewCacheExtension的一个实例,开发者可实现方法getViewForPositionAndType(Recycler recycler, int position, int type)来实现自己的缓存。

2 Recyclerview的四级缓存

2.1 屏幕内缓存/一级缓存(mAttachedScrapmChangedScrap

屏幕内缓存指在屏幕中显示的ViewHolder,这些ViewHolder会缓存在mAttachedScrapmChangedScrap中:

  • mChangedScrap表示数据已经改变的viewHolder列表
  • mAttachedScrap未与RecyclerView分离的ViewHolder列表

ViewHolder只有在满足下面情况才会被添加到mChangedScrap:当它关联的item发生了变化(notifyItemChanged或者 notifyItemRangeChanged被调用),并且ItemAnimator调用ViewHolder#canReuseUpdatedViewHolder方法时,返回了false(返回false表示我们要执行用一个view替换另一个 view的动画,例如淡入淡出动画。true表示动画在view内部发生)。否则,ViewHolder会被添加到mAttachedScrap中。

mChangedScrapmAttachedScrap可以看做是一个层级,都是屏幕上可见itemView,只不过区分了状态(改变和未改变)。

RecyclerView的滑动场景来说,新卡位的复用以及旧卡位的回收机制, 不会涉及到mChangedScrapmAttachedScrap

可以在3种情况下重用更新的ViewHolder

  • setSupportsChangeAnimations(false)
  • notifyDataSetChanged而不是notifyItemChangednotifyItemRangeChanged
  • notifyItemChanged(index, anyObject)

最后一种情况显示了一种很好的方法,当只想更改一些内部元素时,可以避免创建/绑定新的ViewHolder

2.2 屏幕外缓存/二级缓存(mCachedViews

当列表滑动出了屏幕时,ViewHolder会被缓存在mCachedViews ,其大小由mViewCacheMax决定,默认DEFAULT_CACHE_SIZE2,可通过Recyclerview.setItemViewCacheSize()动态设置。

2.3 自定义缓存/三级缓存(ViewCacheExtension

可以自己实现ViewCacheExtension类实现自定义缓存,可通过Recyclerview.setViewCacheExtension()设置。

2.4 缓存池/四级缓存(RecycledViewPool

ViewHolder在首先会缓存在mCachedViews中,当超过了个数(比如默认为2),就会添加到RecycledViewPool中。RecycledViewPool会根据每个ViewTypeViewHolder分别存储在不同的列表中,每个ViewType最多缓存DEFAULT_MAX_SCRAP = 5 x ViewHolder,如果RecycledViewPool没有被多个RecycledView共享,对于线性布局,每个ViewType最多只有一个缓存,如果是网格有多少行就缓存多少个。它们之间的关系如下 :

缓存池

2.5 缓存策略

Recyclerview在获取ViewHolder时按四级缓存的顺序查找,如果没找到就创建(createViewHolder)。其中只有RecycledViewPool找到时才会调用 bindViewHolder,其它缓存不会重新bindViewHolder 流程如下 :

缓存策略

3 总结

通过了解RecyclerView的四级缓存,我们可以知道,RecyclerView最多可以缓存N(屏幕最多可显示的item数) + 2(屏幕外的缓存) + 5 x M (M代表M个ViewType,缓存池的缓存),只有RecycledViewPool找到时才会重新调用bindViewHolder
还需要注意的是,RecycledViewPool可以被多个RecyclerView共享,其缓存个数与ViewType个数、布局相关,如果RecycledViewPool没有被多个RecycledView共享,对于线性布局,每个ViewType最多只有一个缓存,如果是网格布局有多少行就缓存多少个。

参考

https://zhooker.github.io/2017/08/14/关于Recyclerview的缓存机制的理解/

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-11-23 12:28:54  更:2021-11-23 12:31:27 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 5:45:14-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码