前言

上一章,小编介绍了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

image-20220724172908391

1.因为RecyclerView的具体onLayout是交给具体的LayoutManager来实现的,所以回收复用的具体操作是由LayoutManager来完成,在自定义LayoutManager时需考虑这一点,参考系统提供的LinearLayoutManager

2.上图的两个重心是LinearLayoutManager中回收入口的分叉和Recycler中的实际回收情况,而我们在自定义LayoutManager时,回收Holder只需要通过detachAndScrapAttachedViews这一个方法即可,具体是如何进行回收的我们不关心,但需要知道有哪几种,因为这对应了几种缓存,上面已经介绍了四级缓存。

3.缓存池与mCacheViews的关系:

image-20220717144808720

注意:缓存池中保存的只是ViewHolder,没有数据,所以缓存池中的ViewHolder复用还需要绑定

  • fill

    在fill中只考虑了recycleViewHolderInternal这种情况,滑动过程中会触发

回收重要源码截图

如果觉得上述回收流程图理解起来抽象的,可见结合部分源码截图理解。

image-20220717115957690

image-20220717121349370

image-20220717141954608

image-20220717142831116

如果超过mCacheView最大值(2),就加入到缓存池

缓存到缓存池之后,就从mCacheView中移除

从“0”拿出,说明是先进先出的

  • 否则,直接进缓存池 和上面一样都是调用addViewHolderToRecycledViewPool

image-20220717143953794

image-20220717144255403

image-20220717144354585

ScrapData -> ArrayList

mScrap->SpareArray

image-20220717144443187

recycler.scrapView()

image-20220717153414420

ViewHolder的包装源码

image-20220717120045307

image-20220717120201306

image-20220717120910841

复用入口

复用的入口点同样也是两个,分别是布局时与滑动时。

  • onLayout

    上一章中我们在自定义LayoutManager中就是重写的下面的4.onLayoutChildren

image-20220717165422042

  • onTouch

image-20220724174858215

其实二者雷同,从fill入口开始,onLayout与onTouch几乎一样,只是第一张图用的时序图,绘制的比较详细。

总结

其实我们阅读源码了解原理机制,不用记住每个方法的入口、流程细节等,只需要记住大致过程,并理解重要部分。比如RecyclerView的四级缓存,以及回收复用的大致过程。

这章的几个重点:

1.从mAttachedScrap、mChangedScrap、mCachedViews中取出的holder不需要再绑定数据

2.从RecyclerPool取出的holder需要重新绑定数据

3.mAttachedScrap、mChangedScrap缓存的是屏幕看到的holder

参考文章

https://wiwiyiyi.com/RecyclerView%E5%9B%9E%E6%94%B6%E4%B8%8E%E5%A4%8D%E7%94%A8%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90.html#%E5%9B%9B-%E6%80%BB%E7%BB%93