四级缓存
RecyclerView有mAttachedScrap->mCachedViews->ViewCacheExtension->RecycledViewPool四级缓存
mAttachedScrap:缓存屏幕内的ViewHolder,当RecyclerView需要重新layout时,会remove掉所有View,然后再add上去,那这暂时性的remove掉的View就存放在mAttachedScrap里;所以这个缓存主要用在layout时,屏幕内的ViewHolder不能用在滑动时复用,所以它和滑动缓存其实没什么关系
mCachedViews:缓存移出屏幕的ViewHolder,当position一致时才能被复用,复用时不调用onCreateViewHolder也不调用 onBindViewHolder
RecycledViewPool:在mCachedViews满了后,会把一个自己的ViewHolder存到RecycledViewPool,好空出位置来存放最新滑出屏幕的ViewHolder;RecycledViewPool每个type存储数量是5个,type一致就可以被复用,会调用onBindViewHolder重新绑定布局
mViewCacheExtension:这个是留给我们自己扩展的,好像也没怎么用
(注:以下只讲一种ViewType的情况)
缓存:
通过以上对四级缓存的说明,滑动缓存场景里主要用到的是mCacheViews和RecycledViewPool
mCacheViews最大缓存条数:
默认缓存条数 = 2; 预缓存条数 = 一行; 最大缓存条数 = 默认缓存条数 + 预缓存条数
存入mCacheViews时机:
当ViewHolder滑出屏幕外
RecyclerView会预加载一行,由于这一行一开始是不可见的,所以直接放进mCacheViews
mCacheViews超过最大缓存条数后,再有ViewHolder滑出屏幕,就会被放进RecycledViewPool;
复用滑动列表时,依次从mCachedViews->RecycledViewPool二级缓存里取出ViewHolder
屏幕里最多的View的数量?
RecyclerView的布局方式是根据滑动的方向,在滑出的一头删除,而在进入的另一头添加View,所以最多的View数就是一屏能容纳的最多Item数量;
最多创建几个ViewHolder?
如果缓存都没有命中就需要创建新的ViewHolder;考虑极端的情况,如果每次滑出的都是新的position时,mCachedViews缓存无法被复用,RecycledViewPool里如果也没有ViewHolder,那就需要不断创建新的ViewHolder,直到RecycledViewPool里有缓存为止;刚才说到mCachedViews满了之后,ViewHolder会被放进RecycledViewPool;
mCachedViews什么时候满?
mCachedViews达到最大缓存条数
mCachedViews满了时最多创建了多少ViewHolder?
ViewHolderCount = 第一屏数量 + 最大缓存条数 + 1(额外1个)
但忽略了一个问题是,如果一行有多列,每次都是一行一行地滑进滑出,缓存也是一行一行的存,那么需要达到的 最大缓存条数应该是列数的整数倍
Math.ceil(( ViewHolderCount + 1) / 列数) * 列数
经过实践,慢慢滑动时最多创建的ViewHolder数确实是ViewHolderCount,但快速滑动时就要创建列数整数倍个,猜测应该是快速滑动时来不及复用导致的