Recycler缓存机制

来源:互联网 发布:ubuntu如何更新软件源 编辑:程序博客网 时间:2024/06/06 10:34

首先来看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就结束了

原创粉丝点击