Recycler缓存机制

首先来看RecycledViewPool
这是一个静态内部类,内部变量:

private SparseArray<ArrayList<ViewHolder>> mScrap = new SparseArray<ArrayList<ViewHolder>>();
private SparseIntArray mMaxScrap = new SparseIntArray();

mScrap存放的是,每一个viewType对应的缓存viewHolder们,这些viewHolder装在arrayList中
mMaxScrap,每一个viewType对应着最多缓存多少个viewHolder的数量

put和get操作也比较简单
put: 找到viewType对应的arrayList,没有则new一个; 如果达到了最大直,那就不放了,
get:根据viewType找到对应的arrayList,没有就返回null

现在来看Recycler内部类,先看回收view,进入recycleView(View view)方法
开头那些判断先不管,直接进recycleViewHolderInternal方法
重要代码就这段, holder就是view的viewHolder

if (!holder.hasAnyOfTheFlags(ViewHolder.FLAG_INVALID | ViewHolder.FLAG_REMOVED
                        | ViewHolder.FLAG_UPDATE)) {
                    Log.d("xyz", "holder have no flags");
                    // Retire oldest cached view
                    int cachedViewSize = mCachedViews.size();
                    if (cachedViewSize >= mViewCacheMax && cachedViewSize > 0) {
                        Log.d("xyz", "recycle Cached view at 0");
                        recycleCachedViewAt(0);
                        cachedViewSize --;
                    }
                    if (cachedViewSize < mViewCacheMax) {
                        MyRecyclerAdapter.MyViewHolder myViewHolder =
                            (MyRecyclerAdapter.MyViewHolder) holder;
                        Log.d("xyz", "holder add to cache id="+String.valueOf(myViewHolder.id)+
                        " position="+String.valueOf(myViewHolder.getAdapterPosition()));
                        mCachedViews.add(holder);
                        cached = true;
                    }
                }

这个mCachedViews就是一个ArrayList,第一个判断意思是,如果list已经达到最大值,那就把第一个扔到RecycleViewPool,再加到list的最后一个。
第二个判断就是如果list没到最大值,那就加到list里面。正常来说,第二个判断都会执行。
这里其实是二级缓存,第一级是mCachedViews,第二级是RecycleViewPool。

对于recycleCachedViewAt(0)方法,点进去你会发现,它会调用adapter的onViewRecycled方法,而且如果你给Recycler设置了监听RecyclerListener,里面的onViewRecycled也会调用。
进入RecycleViewPool时还会把viewHolder内部的标志位重置。

回收view看完,现在来看获取view
会调用getViewForPosition(int position, boolean dryRun)
1 直接看到方法 getScrapViewForPosition(position, INVALID_TYPE, dryRun) (dryRun为false)
首先从mAttachedScrap开始找,再从隐藏的view找,最后从mCachedViews找。
mCachedViews上面讲过了,来看一下mAttachedScrap,这是个ArrayList。
还记得刚开始的时候,layoutManager的onLayoutChildren会调用2次,第二次调用时,会先调用Recycler的detachAndScrapAttachedViews方法,这个方法会把所有view从RecyclerView detach,再加入mAttachedScrap。
所以这个时候,从mAttachedScrap就能得到。

2 第一个方法得不到,就会尝试从mViewCacheExtension获取。这个是开发者自定义的。

3 还是得不到,就从RecycleViewPool里取

4 还是得不到,那就调用adapter去创建viewHolder

以上就是找viewHolder的过程,找完之后,还要判断要不要bind,主要通过viewHolder的状态位判断。
getViewForPosition就结束了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值