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