RecyclerView复用机制和缓存机制

1. RecyclerView复用机制流程:
以onTouchEvent作为切入口:
在这里插入图片描述
时序图中关键流程简要备注:

  1. 第1步, 代码切入点:
    1)上下滑动会产生ViewHolder–>从OnTouchEvent()的MotionEvent.ACTION_MOVE事件处理;
    2) 从onLayout作为切入口

  2. 第3步,mLayout.scrollVerticallyBy()中的mLayout指LayoutManager类对象,它是RecyclerView内部的 抽象类,LinearLayoutManager继承RecyclerView.LayoutManager,之后以上下滑动为例进行阐述;

  3. 第5步,fill()—>填充item,fill(RecyclerView.Recycler recycler, LayoutState layoutState,
    RecyclerView.State state, boolean stopOnFocusable)方法中的第一个参数RecyclerView.Recycler表示处理缓存(回收)复用

  4. 第7步,View view = layoutState.next(recycler);表示从缓存中拿到一个View进行复用处理,拿到view之后执行addView(view)添加到布局中。

  5. 第8步, recycler.getViewForPosition()–>根据位置拿到复用的View

  6. 第10步,tryGetViewHolderForPositionByDeadline这个非常重要 --》这个方法处理复用机制

  7. 第11步,getChangedScrapViewForPosition从mChangedScrap.get(i)(通过position和id进行获取)中去获取ViewHolder,mChangedScrap是一个ArrayList集合

  8. 第13步,如果从mChangedScrap集合中没有获取到,则利用getScrapOrHiddenOrCachedHolderForPosition方法通过position,首先从mAttachedScrap集合中,如果从mAttachedScrap集合中没获取到,再从mCachedViews集合中进行获取;

  9. 第16步,如果从mCachedViews集合中没有获取到ViewHolder,则利用采用getScrapOrCachedViewForId通过stable id进行查找,流程跟第13步类似,首先从mAttachedScrap集合中没获取到,再从mCachedViews集合中进行获取;

  10. 第19步,mViewCacheExtension是一个抽象类RecyclerView.ViewCacheExtension的对象实例, mViewCacheExtension.getViewForPositionAndType 这个接口其实是google工程师让用户自定义的,先自定义缓存,再自定义复用,这一步一般不要关,不会处理;

  11. 第20步,如果在第19步还是没获取到,就从缓存池中进行获取,调用getRecycledViewPool().getRecycledView()

  12. 第21步,如果从上面的流程中还没有获取到,就通过适配器创建一个ViewHolder,执行mAdapter.createViewHolder()流程,mAdapter指RecyclerView的内部类Adapter;createViewHolder()方法内部会执行onCreateViewHolder()方法,该方法是一个抽象方法

  13. 第23步,假如ViewHolder容器能够拿到,则会执行tryBindViewHolderByDeadline()方法进行绑定数据,tryBindViewHolderByDeadline()–>mAdapter.bindViewHolder()–> onBindViewHolder(),onBindViewHolder是一个抽象方法;

缓存和复用的对象是什么?–> ViewHolder -->可以简单理解为itemView

2. 四级缓存

  1. mChangeScrap与mAttachedScrap
    用来缓存还在屏幕内的ViewHolder
    局部刷新,保存在mAttachedScrap中的直接拿来用,主要是性能优化处理
    mChangeScrap主要是用于动画处理

  2. mCachedViews --> 可以通过setMaxRecycledViews()更改默认大小
    用来缓存移除屏幕之外的ViewHolder
    ArrayList mCachedViews 默认大小 --> DEFAULT_CACHE_SIZE = 2 --> 可以通过setViewCacheSize()更改默认大小
    ArrayList scrapHeap 默认大小 --> DEFAULT_CACHE_SIZE = 5

  3. mViewCacheExtension
    这个的创建和缓存完全由开发者自己控制,系统未往这里添加数据

  4. RecycledViewPool
    ViewHolder缓冲池

以onLayout作为切入口:
在这里插入图片描述
复用 是从 缓存中去取,先有缓存,在有复用。

3. 缓存
在这里插入图片描述
时序图中关键流程简要备注:

  1. 第2步,通过for循环不断获取缓存
  2. 第3步,scrapOrRecycleView()这个方法比较关键,分两者情况进行处理缓存
    ① recycler.recycleViewHolderInternal(viewHolder)
    缓存到mCachedViews(默认大小2)和 RecycledViewPool中(默认大小5)。
    ② recycler.scrapView(view)
    根据下面的条件来判断是缓存到mAttachedScrap 还是mChangedScrap中。—》这个就是一级缓存
if (holder.hasAnyOfTheFlags(ViewHolder.FLAG_REMOVED | ViewHolder.FLAG_INVALID)
                    || !holder.isUpdated() || canReuseUpdatedViewHolder(holder))
  1. 第5步,如果mCacheView满了,取出ViewHolder放到根据viewType(第7步)放到RecycledViewPool(第6步)中,并将mCachedViews集合中第0个位置的remove;

mCachedViews和RecycledViewPool缓存流程:
在这里插入图片描述

mCacheView结构:队列
RecycledViewPool结构:有点类似hashMap

1)屏幕从下往上滑动,滑出1个ViewHolder(item),先放到mCacheView缓存中的index 为0的位置,如果屏幕在滑出1个item,放到index为1的位置;

2)如果屏幕此时在滑出一个ViewHolder,则将mCacheView缓存中index 为0的位置的ViewHolder,根据其ViewType,放到RecycledViewPool缓存对应的ScrapData中,ScrapData中最多只能放5个,超过5就return丢掉,如果没有满就会先将ViewHolder先置空(复位),再添加到ScrapData集合中;

3)将原来mCacheView缓存中index 为1的位置ViewHolder,放到mCacheView缓存中index 为0的位置,再将滑出屏幕的ViewHolder放到mCacheView缓存中index 为1的位置中。

onCreateViewHolder --> 缓存拿不到ViewHolder才会调用的,而不是拿不到数据

从缓存池中复用ViewHolder:需要调用 onBindViewHolder
从CacheView中复用ViewHolder:不用调用 onBindViewHolder
从缓存中没有拿到ViewHolder:会调用 onCreateViewHolder 和 onBindViewHolder

ListView与RecyclerView的区别:
ListView:只能在垂直方向滑动
RecyclerView:支持水平方向滑动,垂直方向滑动,多行多列瀑布流的方式等

ListView:有几个默认的Adapter,分别是ArrayAdapter、CursorAdapter和SimpleCursorAdapter
RecyclerView:Adapter需要自己实现

ListView:拥有子Item的监听函数:AdapterView.OnItemClickListener
RecyclerView:需要自己实现接口,来实现子Item的点击事件,虽然比较麻烦,但是扩展性好

ListView:并不强制使用ViewHolder,如果要使用,则需要自己定义,如果不使用,ListView每次getView()的时候都需要去findViewById,会造成性能下降,滑动卡顿等,所以推荐使用ViewHolder
RecyclerView:必须使用ViewHolder

ListView:两级缓存
1)mActiveViews 用于屏幕内ItemView快速重用
2)mScrapViews 用于缓存离开屏幕的ItemView
RecyclerView:四级缓存
1)mChangeScrap 与 mAttachedScrap 用于屏幕内ItemView 快速重用
2)mCachedViews 默认上限为2,即缓存屏幕外2个ItemView
3)mViewCacheExtension 用户自定义,一般不使用
4)RecycledViewPool 默认上限为5

缓存对象不同,RecyclerView缓存的是ViewHolder,ListView缓存的是View。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值