RecyclerView的回收复用机制
前言
上一章,小编介绍了RecyclerView的高级用法——自定义LayoutManager。今天,我们来从源码的角度深度剖析RecyclerView,主要是对RecyclerView的回收复用机制熟悉掌握。
RecyclerView介绍
RecyclerView可以说是项目必备的系统高级控件,相比于传统的ListVIew,RecyclerView最大的优势就是四级缓存机制,ListView是两级缓存机制(屏幕内可见、屏幕外)。
四级缓存机制
mChangeScrap(主要与动画相关)与mAttachedScrap(一般这两算一级)
用来缓存还在屏幕内的ViewHolder
mCachedViews
用来缓存移除屏幕之外的ViewHolder
mViewCacheExtension
用户的自定义扩展缓存,需要用户自己管理View的创建和缓存
RecyclerViewPool
ViewHolder缓存池
回收复用的入口
上一章中自定义LayoutManager中有 detachAndScrapAttachedViews(recycler!!)
这样一个方法,用于回收ViewHolder。下面就来介绍一下RecyclerView的回收。
回收有两个入口,一是布局onLayout时,二是在fill填充itemVIew时
- onLayout
1.因为RecyclerView的具体onLayout是交给具体的LayoutManager来实现的,所以回收复用的具体操作是由LayoutManager来完成,在自定义LayoutManager时需考虑这一点,参考系统提供的LinearLayoutManager
2.上图的两个重心是LinearLayoutManager中回收入口的分叉和Recycler中的实际回收情况,而我们在自定义LayoutManager时,回收Holder只需要通过detachAndScrapAttachedViews这一个方法即可,具体是如何进行回收的我们不关心,但需要知道有哪几种,因为这对应了几种缓存,上面已经介绍了四级缓存。
3.缓存池与mCacheViews的关系:
注意:缓存池中保存的只是ViewHolder,没有数据,所以缓存池中的ViewHolder复用还需要绑定
fill
在fill中只考虑了recycleViewHolderInternal这种情况,滑动过程中会触发
回收重要源码截图
如果觉得上述回收流程图理解起来抽象的,可见结合部分源码截图理解。
如果超过mCacheView最大值(2),就加入到缓存池
缓存到缓存池之后,就从mCacheView中移除
从“0”拿出,说明是先进先出的
- 否则,直接进缓存池 和上面一样都是调用
addViewHolderToRecycledViewPool
ScrapData -> ArrayList
mScrap->SpareArray
recycler.scrapView()
ViewHolder的包装源码
复用入口
复用的入口点同样也是两个,分别是布局时与滑动时。
onLayout
上一章中我们在自定义LayoutManager中就是重写的下面的
4.onLayoutChildren
- onTouch
其实二者雷同,从fill入口开始,onLayout与onTouch几乎一样,只是第一张图用的时序图,绘制的比较详细。
总结
其实我们阅读源码了解原理机制,不用记住每个方法的入口、流程细节等,只需要记住大致过程,并理解重要部分。比如RecyclerView的四级缓存,以及回收复用的大致过程。
这章的几个重点:
1.从mAttachedScrap、mChangedScrap、mCachedViews中取出的holder不需要再绑定数据
2.从RecyclerPool取出的holder需要重新绑定数据
3.mAttachedScrap、mChangedScrap缓存的是屏幕看到的holder