RecyclerView缓存机制

1、 ViewHolder

1.1 作用

ViewHolder是对RecyclerView上的ItemView的封装,它是RecyclerView缓存的载体。它封装了以下属性:

  1. View itemView:对应RecyclerView的子View
  2. int mPosition:View当前对应数据在数据源中的位置
  3. int mOldPosition:View上次绑定的数据在数据源中的位置
  4. long mItemId:可以判断ViewHolder是否需要重新绑定数据
  5. int mItemViewType:itemView对应的类型
  6. int mPreLayoutPosition:在预布局阶段ViewHolder对应数据在数据源中的位置
  7. int mFlags:ViewHolder对应的标记位
  8. List mPayloads:实现局部刷新
  9. Recycler mScrapContainer:如果不为空,表示ViewHolder是存放在Scrap缓存中

1.2 flag

  • FLAG_BOUND:ViewHolder对应的View已经绑定好了数据,无需重新绑定
  • FLAG_UPDATE:数据发生了变化,View需要重新绑定
  • FLAG_INVALID:数据失效了,View需要重新绑定
  • FLAG_REMOVED:数据从数据源中删除,View在消失动画中仍然有用
  • FLAG_NOT_RECYCLABLE:ViewHolder不能被回收,ViewHolder对应ItemView做动画时需要保证ViewHolder不能被回收掉
  • FLAG_RETURNED_FROM_SCRAP:从scrap缓存中获取到的ViewHolder
  • FLAG_IGNORE:如果回收该类型的ViewHolder会报错
  • FLAG_TMP_DETACHED:表示ItemView从RecyclerView上DETACHED了,detach和remove的区别是,remove会将View从ViewGroup的children数组中删除并且刷新ViewGroup,detach只会删除不会触发刷新
  • FLAG_ADAPTER_FULLUPDATE:表示ViewHolder需要全量更新,如果没有设置该标志位,则是局部更新
  • FLAG_MOVED:当ViewHolder的位置发生变化,做动画时需要使用
  • FLAG_APPEARED_IN_PRE_LAYOUT:ViewHolder出现在预布局中,需要做APPEARED动画

2、缓存架构

2.1 四级缓存

  1. ArrayList mAttachedScrap & ArrayListmChangedScrap
  2. ArrayList mCachedViews
  3. ViewCacheExtension mViewCacheExtension
  4. RecycledViewPool mRecyclerPool
    在这里插入图片描述
    由图可知,RecyclerView缓存是一个四级缓存的架构。当然,从RecyclerView的代码注释来看,官方认为只有三级缓存,即mCachedViews是一级缓存,mViewCacheExtension是二级缓存,mRecyclerPool是三级缓存。从开发者的角度来看,mAttachedScrap和mChangedScrap对开发者是不透明的,官方并未暴露出任何可以改变他们行为的方法。
public final class Recycler {
		//1、Scrap缓存
        final ArrayList<ViewHolder> mAttachedScrap = new ArrayList<>();
        ArrayList<ViewHolder> mChangedScrap = null;
	
		//2、mCachedViews缓存
        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;
		//4、mRecyclerPool缓存
        RecycledViewPool mRecyclerPool;
		
		//3、mViewCacheExtension缓存
        private ViewCacheExtension mViewCacheExtension;
        ........
}

2.2 scrap缓存

scrap缓存由mAttachedScrap和mChangedScrap两个缓存组成,在RecyclerView调用dispatchLayout时会使用该缓存,保存RecyclerView上的子View。

两部分组成:

  • mAttachedScrap
  • mChangedScrap

缓存特性:

  1. 对应的数据结构是ArrayList;
  2. 缓存大小没有限制,大小等于RecyclerView子View的个数;
  3. 该缓存中的ViewHolder无需重新绑定,只要ViewHolder的position和数据源中的position对应上了;
  4. 调用notifyItemRemoved、notifyItemMoved、notifyItemInserted方法,ViewHolder放入mAttachedScrap中;
  5. 调用notifyItemChanged(int position, Object payload),如果payload!=null ViewHolder放入mAttachedScrap中,否则ViewHolder放入mChangedScrap中;
  6. 调用notifyDataSetChanged()时,如果Adapter.hasStableIds返回true,ViewHolder放入mAttachedScrap中,否则会将ViewHolder回收到非scrap缓存中;
  7. LinearLayoutManager.layoutForPredictiveAnimations()阶段,mAttachedScrap数组剩下的ViewHolder是被挤出屏幕的.

2.3 mCachedViews缓存

缓存特性:

  1. 对应的数据结构是ArrayList;
  2. 缓存大小有限制,默认缓存大小为2,可以修改默认缓存大小。如果使用GridLayoutManager建议设置为列的个数;
  3. 该缓存中的ViewHolder无需重新绑定,只要ViewHolder的position和数据源中的position和itemType对应上了;
  4. 该缓存的特性是FIFO;
  5. ViewHolder mFlag如果有FLAG_INVALID、FLAG_REMOVED、FLAG_UPDATE、FLAG_ADAPTER_POSITION_UNKNOWN之一,不会放入该缓存;
  6. 当RecyclerView滑动时会将ViewHolder放入该缓存或者从该缓存获取ViewHolder.

mCacheViews可以通过如下方法,改变缓存的大小:

public void setItemViewCacheSize(int size) {
    mRecycler.setViewCacheSize(size);
}

2.4 ViewCacheExtension

优化RecyclerView初始化时创建View对主线程阻塞的时长。

在空闲时刻进行RecyclerView部分item的初始化

2.5 RecyclerViewPool

缓存特性:

  1. 对应的数据结构是SparseArray,根据itemType将缓存分组,组的数据结构是ScrapData;
  2. ScrapData对应的数据结构是ArrayList,每个itemType对应的ScrapData的缓存大小默认值是5,可以修改缓存大小;
  3. 该缓存中的ViewHolder需要重新绑定数据;
  4. 可以提供给多个RecyclerView共享。

RecyclerViewPool缓存可以针对多ItemType,设置缓存大小。默认每个ItemType的缓存个数是5。而且该缓存可以给多个RecyclerView共享。由于默认缓存个数为5,假设某个新闻App,每屏幕可以展示10条新闻,那么必然会导致缓存命中失败,频繁导致创建ViewHolder影响性能。所以需要扩大缓存size。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值