RecyclerView的缓存机制
2021-01-09 本文已影响0人
来lol里
源码的追溯流程
onTouchEvent
Move
scrollByInternal
mLayout.scrollVerticallyBy(y, mRecycler, mState);
LinearLayoutManager.scrollBy();
fill(recycler, mLayoutState, state, false);
(while循环)layoutChunk();
layoutState.next(recycler);
recycler.getViewForPosition(mCurrentPosition);
tryGetViewHolderForPositionByDeadline//核心方法在这里
四级缓存
-
mAttachedScrap和mChangedScrap
mAttachedScrap 缓存的是从屏幕上分离出来的ViewHolder,但是又即将添加到屏幕上去的ViewHolder。比如说,RecyclerView上下滑动,滑出一个新的Item,此时会重新调用LayoutManager的onLayoutChildren方法,从而会将屏幕上所有的ViewHolder先scrap掉(含义就是废弃掉),添加到mAttachedScrap里面去,然后在重新布局每个ItemView时,会从优先mAttachedScrap里面获取,这样效率就会非常的高。这个过程不会重新onBindViewHolder。
mChangedScrap 这个缓存和上边的mAttachedScrap是一样的,唯一不同的从名字也可以看出来,它存放的是发生了变化的ViewHolder,如果使用到了这里的缓存的ViewHolder是要重新走Adapter的绑定方法onBindViewHolder的。这个和上个保存的都是dettach掉的ViewHolder。
具体方法在
void scrapView(View view) {
final ViewHolder holder = getChildViewHolderInt(view);
if (holder.hasAnyOfTheFlags(ViewHolder.FLAG_REMOVED | ViewHolder.FLAG_INVALID)
|| !holder.isUpdated() || canReuseUpdatedViewHolder(holder)) {
if (holder.isInvalid() && !holder.isRemoved() && !mAdapter.hasStableIds()) {
throw new IllegalArgumentException("Called scrap view with an invalid view."
+ " Invalid views cannot be reused from scrap, they should rebound from"
+ " recycler pool." + exceptionLabel());
}
holder.setScrapContainer(this, false);
mAttachedScrap.add(holder);
} else {
if (mChangedScrap == null) {
mChangedScrap = new ArrayList<ViewHolder>();
}
holder.setScrapContainer(this, true);
mChangedScrap.add(holder);
}
}
mCachedViews 默认大小为2,通常用来存储预取的ViewHolder,同时在回收ViewHolder时,也会可能存储一部分的ViewHolder,这部分的ViewHolder通常来说,意义跟一级缓存差不多。这个变量同样是一个存放ViewHolder对象的ArrayList,但是这个不同于上面的两个里面存放的是dettach掉的视图,它里面存放的是已经remove掉的视图,已经和RV分离的关系的视图,但是它里面的ViewHolder依然保存着之前的信息,比如position、和绑定的数据等等。这一级缓存是有容量限制的,默认是2。先进先出,当超过两个了,前一个被放入RecyclerViewPool中,后边的add进来。
ViewCacheExtension 自定义缓存用到较少
RecyclerViewPool 默认大小为5,这里面保存的ViewHolder不仅仅是removed掉的视图,而且是恢复了出厂设置的视图,任何绑定过的痕迹都没有了,想用这里缓存的ViewHolder是一定要走onBindViewHolder 的绑定方法的。而且我们知道RV支持多布局,所以这里的缓存是按照itemType来分开存储的,即每种itemType最多缓存5个。
image.png