Recycler组成
RecyclerView的缓存主要委托给了Recycler,先了解下组成
public final class Recycler {
final ArrayList<RecyclerView.ViewHolder> mAttachedScrap = new ArrayList();
ArrayList<RecyclerView.ViewHolder> mChangedScrap = null;
final ArrayList<RecyclerView.ViewHolder> mCachedViews = new ArrayList();
private final List<RecyclerView.ViewHolder> mUnmodifiableAttachedScrap;
private int mRequestedCacheMax;
int mViewCacheMax;
RecyclerView.RecycledViewPool mRecyclerPool;
private RecyclerView.ViewCacheExtension mViewCacheExtension;
static final int DEFAULT_CACHE_SIZE = 2;
//...
}
* 1.一级缓存:mAttachedScrap
* 2.二级缓存:mCacheViews
* 3.三级缓存:mViewCacheExtension
* 4.四级缓存:mRecyclerPool
在RecyclerView的绘制流程中分析过,layoutManager会在layoutChunk方法中对view进行获取添加测量等操作,如下所示
//LinerLayoutManager.java
void layoutChunk(Recycler recycler, State state, LinearLayoutManager.LayoutState layoutState, LinearLayoutManager.LayoutChunkResult result) {
View view = layoutState.next(recycler);
// 执行addView
// 测量view
}
//LinearLayoutManager.LayoutState
View next(Recycler recycler) {
// mScrapList初始化为空,且仅在layoutForPredictiveAnimations被赋值,执行完后又被设置为null
if (this.mScrapList != null) {
return this.nextViewFromScrapList();
} else {
// * 进入该分支
View view = recycler.getViewForPosition(this.mCurrentPosition);
this.mCurrentPosition += this.mItemDirection;
return view;
}
}
//RecyclerView.Recycler
@NonNull
public View getViewForPosition(int position) {
return this.getViewForPosition(position, false);
}
View getViewForPosition(int position, boolean dryRun) {
return this.tryGetViewHolderForPositionByDeadline(position, dryRun, 9223372036854775807L).itemView;
}
tryGetViewHolderForPositionByDeadline
该方法为获取缓存viewHolder核心方法
//RecyclerView.Recycler
@Nullable
RecyclerView.ViewHolder tryGetViewHolderForPositionByDeadline(int position, boolean dryRun, long deadlineNs) {
if (position >= 0 && position < RecyclerView.this.mState.getItemCount()) {
boolean fromScrapOrHiddenOrCache = false;
RecyclerView.ViewHolder holder = null;
//[0] 从changed Scrap获取holder
if (RecyclerView.this.mState.isPreLayout()) {
//preLayout默认是false,只有有动画的时候才为true?
holder = this.getChangedScrapViewForPosition(position);
fromScrapOrHiddenOrCache = holder != null;
}
//[1] 从scrap中获取holder
if (holder == null) {
holder = this.getScrapOrHiddenOrCachedHolderForPosition(position, dryRun);
if (holder != null) {
// 检查该holder是否与holder对应postion
if (!this.validateViewHolderForOffsetPosition(holder)) {
// 如果信息不符
if (!dryRun) {
holder.addFlags(4);
// 从scrap移除
if (holder.isScrap()) {
RecyclerView.this.removeDetachedView(holder.itemView, false);
holder.unScrap();
} else if (holder.wasReturnedFromScrap()) {
holder.clearReturnedFromScrapFlag();
}
// 将该holder放入mCachedViews或者mRecyclerPool中
this.recycleViewHolderInternal(holder);
}
//设置为空
holder = null;
} else {
fromScrapOrHiddenOrCache = true;
}
}
}
int offsetPosition;
int type;
if (holder == null) {
offsetPosition = RecyclerView.this.mAdapterHelper.findPositionOffset(position);
if (offsetPosition < 0 || offsetPosition >= RecyclerView.this.mAdapter.getItemCount()) {
throw new IndexOutOfBoundsException("Inconsistency detected. Invalid item position " + position + "(offset:" + offsetPosition + ")." + "state:" + RecyclerView.this.mState.getItemCount() + RecyclerView.this.exceptionLabel());
}
type = RecyclerView.this.mAdapter.getItemViewType(offsetPosition);
if (RecyclerView.this.mAdapter.hasStableIds()) {
holder = this.getScrapOrCachedViewForId(RecyclerView.this.mAdapter.getItemId(offsetPosition), type, dryRun);
if (holder != null) {
holder.mPosition = offsetPosition;
fromScrapOrHiddenOrCache = true;
}
}
// 自定义缓存
if (holder == null && this.mViewCacheExtension != null) {
View view = this.mViewCacheExtension.getViewForPositionAndType(this, position, type);
if (view != null) {
holder = RecyclerView.this.getChildViewHolder(view);
if (holder == null) {
throw new IllegalArgumentException("getViewForPositionAndType returned a view which does not have a ViewHolder" + RecyclerView.this.exceptionLabel());
}
if (holder.shouldIgnore()) {
throw new IllegalArgumentException("getViewForPositionAndType returned a view that is ignored. You must call stopIgnoring before returning this view." + RecyclerView.this.exceptionLabel());
}
}
}
// 从缓存池中获取
if (holder == null) {
holder = this.getRecycledViewPool().getRecycledView(type);
if (holder != null) {
holder.resetInternal();
if (RecyclerView.FORCE_INVALIDATE_DISPLAY_LIST) {
this.invalidateDisplayListInt(holder);
}
}
}
// 创建
if (holder == null) {
long start = RecyclerView.this.getNanoTime();
if (deadlineNs != 9223372036854775807L && !this.mRecyclerPool.willCreateInTime(type, start, deadlineNs)) {
return null;
}
holder = RecyclerView.this.mAdapter.createViewHolder(RecyclerView.this, type