RecycleView的四级缓存

2021-10-16  本文已影响0人  破晓11

Recycler 中ArrayList<ViewHolder> mAttachedScrap 是缓存RecycleView做动画时,被detach的viewHolder, ArrayList<ViewHolder> mChangedScrap 缓存刷新时,被detach的viewHolder ,ArrayList<ViewHolder> mCachedViews  以及Viewholder的缓存,最多两个,

RecycledViewPool 缓存池View(这个默认5个),当mCachedView装满时,放入这个RecycledViewPool中

在recycleViewHolderInternal中,当mCachedViews的大小超过两个时候,再来一个viewHolder时,会把新的添加进去,给第0个放到RecycledViewPool中:

if (cachedViewSize >=mViewCacheMax && cachedViewSize >0) {

recycleCachedViewAt(0);

    cachedViewSize--;

}

在recycleCachedViewAt(0);

ViewHolder viewHolder =mCachedViews.get(cachedViewIndex);

这个cachedViewIndex就是0,取出mCachedViews第一个,从mCachedViews中移除

addViewHolderToRecycledViewPool(viewHolder, true);

mCachedViews.remove(cachedViewIndex);

在addViewHolderToRecycledViewPool(@NonNull ViewHolder holder, boolean dispatchRecycled)这个里面通过调用getRecycledViewPool().putRecycledView(holder);给ViewHolder中的View添加到mCachedViews

在ViewHoldergetScrapOrHiddenOrCachedHolderForPosition(int position, boolean dryRun)中,调用scrapView(view);

在scrapView(view);中

final ViewHolder holder =getChildViewHolderInt(view);

if (holder.hasAnyOfTheFlags(ViewHolder.FLAG_REMOVED | ViewHolder.FLAG_INVALID)

|| !holder.isUpdated() || canReuseUpdatedViewHolder(holder)) {

holder.setScrapContainer(this, false);

    mAttachedScrap.add(holder);  //添加动画ViewHolder

}else {

if (mChangedScrap ==null) {

mChangedScrap =new ArrayList();

    }

holder.setScrapContainer(this, true);

    mChangedScrap.add(holder); //添加刷新ViewHolder

}

那么RecycleView是怎样进行ViewHolder的回收的呢,在LinearLayoutManager中:

int fill(RecyclerView.Recycler recycler, LayoutState layoutState,

RecyclerView.State state,boolean stopOnFocusable) {

layoutChunk(recycler, state, layoutState, layoutChunkResult);

      recycleByLayoutState(recycler, layoutState);}

在recycleByLayoutState(recycler, layoutState);这这个里面

private void recycleByLayoutState(RecyclerView.Recycler recycler, LayoutState layoutState) {if (layoutState.mLayoutDirection == LayoutState.LAYOUT_START) {

recycleViewsFromEnd(recycler, layoutState.mScrollingOffset);

}else {

recycleViewsFromStart(recycler, layoutState.mScrollingOffset);

}

}

先看一下recycleViewsFromStart(recycler, layoutState.mScrollingOffset);这个方法

private void recycleViewsFromStart(RecyclerView.Recycler recycler,int dt) {

               recycleChildren(recycler, childCount -1, i);

}

在recycleChildren中进行了View的回收

private void recycleChildren(RecyclerView.Recycler recycler,int startIndex,int endIndex) {

if (endIndex > startIndex) {

for (int i = endIndex -1; i >= startIndex; i--) {

removeAndRecycleViewAt(i, recycler);

}

}else {

for (int i = startIndex; i > endIndex; i--) {

removeAndRecycleViewAt(i, recycler);

}

}

}

public void removeAndRecycleViewAt(int index, Recycler recycler) {

final View view = getChildAt(index);

removeViewAt(index);

recycler.recycleView(view);

}

public void recycleView(View view) {

   ViewHolder holder =getChildViewHolderInt(view);

if (holder.isTmpDetached()) {

removeDetachedView(view,false);

}

recycleViewHolderInternal(holder);

}

在recycleViewHolderInternal中,当mCachedViews的大小超过两个时候,再来一个viewHolder时,会把新的添加进去,给第0个放到RecycledViewPool中:

void recycleViewHolderInternal(ViewHolder holder) {

            int cachedViewSize =mCachedViews.size();

if (cachedViewSize >=mViewCacheMax && cachedViewSize >0) {

recycleCachedViewAt(0);

cachedViewSize--;

}

int targetCacheIndex = cachedViewSize;

if (!cached) {

//将回收的View放入到RecycleViewPool中

addViewHolderToRecycledViewPool(holder,true);

recycled =true;

}

}

void addViewHolderToRecycledViewPool(ViewHolder holder,boolean dispatchRecycled) {

clearNestedRecyclerViewIfNotNested(holder);

holder.itemView.setAccessibilityDelegate(null);

if (dispatchRecycled) {

dispatchViewRecycled(holder);

}

holder.mOwnerRecyclerView =null;

getRecycledViewPool().putRecycledView(holder);

}

//使用adapter回收ViewHolder

void dispatchViewRecycled(ViewHolder holder) {

if (mRecyclerListener !=null) {

mRecyclerListener.onViewRecycled(holder);

}

if (mAdapter !=null) {

mAdapter.onViewRecycled(holder);

}

if (mState !=null) {

mViewInfoStore.removeViewHolder(holder);

}

if (DEBUG) Log.d(TAG,"dispatchViewRecycled: " + holder);

}

public void putRecycledView(ViewHolder scrap) {

final int viewType = scrap.getItemViewType();

final ArrayList scrapHeap = getScrapDataForType(viewType).mScrapHeap;

if (mScrap.get(viewType).mMaxScrap <= scrapHeap.size()) {

return;

}

scrap.resetInternal();

scrapHeap.add(scrap);

}

SparseArray类型的mScrap中添加了以viewType为key,scrapData为value的对象。mScrap是RecycledViewPool中维护的一个SparseArray结构的map集合。回收来的东西放到了这里。

private ScrapData getScrapDataForType(int viewType) {

ScrapData scrapData =mScrap.get(viewType);

if (scrapData ==null) {

scrapData =new ScrapData();

mScrap.put(viewType, scrapData);

}

return scrapData;

}

RecycleView怎样进行复用

void layoutChunk(RecyclerView.Recycler recycler, RecyclerView.State state,

LayoutState layoutState, LayoutChunkResult result) {

View view = layoutState.next(recycler);

if (layoutState.mScrapList ==null) {

if (mShouldReverseLayout == (layoutState.mLayoutDirection

            == LayoutState.LAYOUT_START)) {

addView(view);//添加view

}else {

addView(view,0);//添加view

}

}else {

if (mShouldReverseLayout == (layoutState.mLayoutDirection

            == LayoutState.LAYOUT_START)) {

addDisappearingView(view);

}else {

addDisappearingView(view,0);

}

}

measureChildWithMargins(view,0,0);//测量子view

layoutDecoratedWithMargins(view, left, top, right, bottom);//布局子view

}

//获取要布局的下一个元素的视图

View next(RecyclerView.Recycler recycler) {

if (mScrapList !=null) {

return nextViewFromScrapList();

}

final View view = recycler.getViewForPosition(mCurrentPosition);

mCurrentPosition +=mItemDirection;

return view;

}

在recyclerView中根据position获得视图

public View getViewForPosition(int position) {

return getViewForPosition(position,false);

}

View getViewForPosition(int position,boolean dryRun) {

return tryGetViewHolderForPositionByDeadline(position, dryRun,FOREVER_NS).itemView;

}

ViewHolder tryGetViewHolderForPositionByDeadline(int position,

boolean dryRun,long deadlineNs) {

ViewHolder holder =null;

// 0) If there is a changed scrap, try to find from there

if (mState.isPreLayout()) {

//通过position从Recycler中的mChangedScrap寻找viewHolder

holder = getChangedScrapViewForPosition(position);

fromScrapOrHiddenOrCache = holder !=null;

}

if (holder ==null) {

//根据position从scrap或隐藏的view,或缓存中寻找view

holder = getScrapOrHiddenOrCachedHolderForPosition(position, dryRun);

}

if (holder ==null) {

final int type =mAdapter.getItemViewType(offsetPosition);

// 2) Find from scrap/cache via stable ids, if exists

    if (mAdapter.hasStableIds()) {

//通过id从scrap或者mCacherView中获取viewHolder

holder = getScrapOrCachedViewForId(mAdapter.getItemId(offsetPosition),

type, dryRun);

}

if (holder ==null &&mViewCacheExtension !=null) {

   final View view =mViewCacheExtension

            .getViewForPositionAndType(this, position, type);

if (view !=null) {

//通过childe获取viewHolder

holder = getChildViewHolder(view);

}

}

//从RecyclerViewRool池中获取

holder = getRecycledViewPool().getRecycledView(type);

if (holder !=null) {

holder.resetInternal();

if (FORCE_INVALIDATE_DISPLAY_LIST) {

invalidateDisplayListInt(holder);

}

if (holder ==null) {

long start = getNanoTime();

if (deadlineNs !=FOREVER_NS

            && !mRecyclerPool.willCreateInTime(type, start, deadlineNs)) {

// abort - we have a deadline we can't meet

        return null;

}

//缓存中获取不到viewholder,就自己创建viewHolder

holder =mAdapter.createViewHolder(RecyclerView.this, type);

}

}

}

}

recyclerView用了四级缓存,mAttachedScrap是第一缓存,根据position或者id从mAttachedScrap获取viewHolder,第二级缓存就是从mCachedViews中获取viewHolder,第三级缓存是自定义缓存,通过调用getChildViewHolder获取,第四级缓存是从RecyclerViewPool中获取,当所有的缓存中都获取不到的时候,就自己创建viewHolder

上一篇 下一篇

猜你喜欢

热点阅读