一、缓存机制
分析RecyclerView
缓存机制源码的一系列文章,分析的很清楚:
1. 总结
RecycleView的四级缓存是由三个类共同作用完成的,Recycler
、RecycledViewPool
和ViewCacheExtension
。
Recycler
用于管理已经废弃或者与RecyclerView
分离的ViewHolder
,这里面有两个重要的成员
屏幕内缓存:屏幕内缓存指在屏幕中显示的ViewHolder
,这些ViewHolder
会缓存在mAttachedScrap
、mChangedScrap
中。
mChangedScrap:表示数据已经改变的viewHolder列表
mAttachedScrap:未与RecyclerView分离的ViewHolder列表
屏幕外缓存:当列表滑动出了屏幕时,ViewHolder
会被缓存在 mCachedViews
,其大小由mViewCacheMax
决定,默认DEFAULT_CACHE_SIZE为2,可通过Recyclerview.setItemViewCacheSize()
动态设置。
ViewCacheExtension
开发者可自定义的一层缓存,是虚拟类ViewCacheExtension
的一个实例,开发者可实现方法getViewForPositionAndType(Recycler recycler, int position, int type)
来实现自己的缓存。
RecycledViewPool
RecycledViewPool
类是用来缓存ViewHolder
用,如果多个RecyclerView
之间用setRecycledViewPool(RecycledViewPool)
设置同一个RecycledViewPool
,他们就可以共享ViewHolder
。
1.1 四级缓存
//1.一级缓存:mAttachedScrap 一级缓存中用来存储屏幕中显示的ViewHolde
final ArrayList<ViewHolder> mAttachedScrap = new ArrayList<>();
//2.二级缓存:mCacheViews 用来存储屏幕外的缓存
final ArrayList<ViewHolder> mCachedViews = new ArrayList<ViewHolder>();
//3.三级缓存:mViewCacheExtension 根据coder自己定义的缓存规则
private ViewCacheExtension mViewCacheExtension;
//4.四级缓存:mRecyclerPool 当屏幕外缓存的大小大于2,便放入mRecyclerPool中缓存。
RecycledViewPool mRecyclerPool;
Recycler有4个层次用于缓存ViewHolder对象,优先级从高到底依次为ArrayList mAttachedScrap、ArrayList mCachedViews、ViewCacheExtension mViewCacheExtension、RecycledViewPool mRecyclerPool。如果四层缓存都未命中,则重新创建并绑定ViewHolder对象
1.2 缓存性能
缓存 | 重新创建ViewHolder |
重新绑定数据 |
---|---|---|
mAttachedScrap | false | false |
mCachedViews | false | false |
mRecyclerPool | false | true |
1.3 缓存容量
-
mAttachedScrap
:没有大小限制,但最多包含屏幕可见表项。 -
mCachedViews
:默认大小限制为2,放不下时,按照先进先出原则将最先进入的ViewHolder
存入回收池以腾出空间。 -
mRecyclerPool
:对ViewHolder
按viewType
分类存储(通过SparseArray
),同类ViewHolder
存储在默认大小为5的ArrayList
中。
1.4 缓存用途
-
mAttachedScrap
:用于布局过程中屏幕可见表项的回收和复用。 -
mCachedViews
:用于移出屏幕表项的回收和复用,且只能用于指定位置的表项,有点像“回收池预备队列”,即总是先回收到mCachedViews
,当它放不下的时候,按照先进先出原则将最先进入的ViewHolder
存入回收池。 -
mRecyclerPool
:用于移出屏幕表项的回收和复用,且只能用于指定viewType
的表项
1.5 缓存结构
-
mAttachedScrap
:ArrayList
-
mCachedViews
:ArrayList
-
mRecyclerPool
:对ViewHolder
按viewType
分类存储在SparseArray
中,同类ViewHolder
存储在ScrapData
中的ArrayList
中
1.6 缓存存入步骤
-
第一级缓存执行流程
RecyclerView.scrollBy()–>RecyclerView.scrollByInternal()–>RecyclerView.resumeRequestLayout()–>RecyclerView.dispatchLayout()–>RecyclerView.dispatchLayoutStep1()–>LayoutManager.onLayoutChildren()–>LayoutManager.scrapOrRecycleView()–>Recycler.scrapView() -
第二级缓存执行流程 执行条件 第一级缓存不要的才给第二级缓存
Recycler.recycleViewHolderInternal() -
第四级缓存 第二级缓存满了 才给第四级缓存
1.7 缓存获取步骤
LinearLayoutManager.onLayoutChildren()–>LinearLayoutManager.fill()–>LinearLayoutManager.layoutChunk()–>LayoutState.next()–>Recycler.getViewForPosition()–>Recycler.getViewForPosition()–>Recycler.tryGetViewHolderForPositionByDeadline()