缓存scrapOrRecycleView()
根据条件判断 -> 一级缓存 / 二、四级缓存
private void scrapOrRecycleView(Recycler recycler, int index, View view) {
final ViewHolder viewHolder = getChildViewHolderInt(view);
if (viewHolder.shouldIgnore()) {
if (DEBUG) {
Log.d(TAG, "ignoring view " + viewHolder);
}
return;
}
if (viewHolder.isInvalid() && !viewHolder.isRemoved()
&& !mRecyclerView.mAdapter.hasStableIds()) {
removeViewAt(index); // 移除视图
recycler.recycleViewHolderInternal(viewHolder); // 二、四级缓存
} else {
detachViewAt(index); // 暂时从视图层级结构中分离视图
recycler.scrapView(view); // 一级缓存
mRecyclerView.mViewInfoStore.onViewDetached(viewHolder);
}
}
scrapView(View view)
public final class Recycler {
// ArrayList -> 存储屏幕中的ViewHolder
final ArrayList<ViewHolder> mAttachedScrap = new ArrayList<>();
ArrayList<ViewHolder> mChangedScrap = null;
//……
void scrapView(View view) {
final ViewHolder holder = getChildViewHolderInt(view);
mAttachedScrap
if (holder.hasAnyOfTheFlags(ViewHolder.FLAG_REMOVED | ViewHolder.FLAG_INVALID)
|| !holder.isUpdated() || canReuseUpdatedViewHolder(holder)) {
//……
holder.setScrapContainer(this, false);
mAttachedScrap.add(holder); // 缓存屏幕中未改变的ViewHolder
} else {
mChangedScrap
if (mChangedScrap == null) {
mChangedScrap = new ArrayList<ViewHolder>();
}
holder.setScrapContainer(this, true);
mChangedScrap.add(holder); // 缓存屏幕中如`notifyItemChanged`改变的ViewHolder
}
}
recycleViewHolderInternal(viewHolder)
void recycleViewHolderInternal(ViewHolder holder) {
// ……省略这部分异常处理及条件参数的设置
if (forceRecycle || holder.isRecyclable()) {
if (mViewCacheMax > 0 // mViewCacheMax = DEFAULT_CACHE_SIZE = 2 默认2个
&& !holder.hasAnyOfTheFlags(ViewHolder.FLAG_INVALID
| ViewHolder.FLAG_REMOVED
| ViewHolder.FLAG_UPDATE
| ViewHolder.FLAG_ADAPTER_POSITION_UNKNOWN)) {
mCachedView
// Retire oldest cached view
int cachedViewSize = mCachedViews.size();
if (cachedViewSize >= mViewCacheMax && cachedViewSize > 0) {
// 二级缓存已满且新ViewHolder进入 -> 最早添加的ViewHolder -> RecycledViewPool
recycleCachedViewAt(0);
cachedViewSize--;
}
// 计算targetCacheIndex,避免向缓存中添加新的视图时,覆盖最近预取的视图
int targetCacheIndex = cachedViewSize;
if (ALLOW_THREAD_GAP_WORK
&& cachedViewSize > 0
&& !mPrefetchRegistry.lastPrefetchIncludedPosition(holder.mPosition)) {
// when adding the view, skip past most recently prefetched views
int cacheIndex = cachedViewSize - 1;
while (cacheIndex >= 0) {
int cachedPos = mCachedViews.get(cacheIndex).mPosition;
if (!mPrefetchRegistry.lastPrefetchIncludedPosition(cachedPos)) {
break;
}
cacheIndex--;
}
targetCacheIndex = cacheIndex + 1;
}
mCachedViews.add(targetCacheIndex, holder);
cached = true;
}
- 缓存池
RecycledViewPool
// -> 缓存池RecycledViewPool
if (!cached) {
addViewHolderToRecycledViewPool(holder, true);
recycled = true;
}
} else { // ……动画过程中回收 -> 异常信息 }
// even if the holder is not removed, we still call this method so that it is removed
// from view holder lists.
mViewInfoStore.removeViewHolder(holder);
if (!cached && !recycled && transientStatePreventsRecycling) {
holder.mOwnerRecyclerView = null;
}
}
自定义缓存ViewCacheExtension
void setViewCacheExtension(ViewCacheExtension extension) {
mViewCacheExtension = extension;
}
addViewHolderToRecycledViewPool(holder, true)
void addViewHolderToRecycledViewPool(@NonNull ViewHolder holder, boolean dispatchRecycled) {
clearNestedRecyclerViewIfNotNested(holder); // 清除ViewHolder绑定的数据
View itemView = holder.itemView;
// ……
if (dispatchRecycled) {
dispatchViewRecycled(holder);
}
holder.mOwnerRecyclerView = null;
// 添加到缓存池`RecycledViewPool`中
getRecycledViewPool().putRecycledView(holder); // DEFAULT_MAX_SCRAP = 5
}
putRecycledView(ViewHolder scrap)
public void putRecycledView(ViewHolder scrap) {
final int viewType = scrap.getItemViewType();
final ArrayList<ViewHolder> scrapHeap = getScrapDataForType(viewType).mScrapHeap;
// 每种类型viewType的ViewHolder -> 默认mMaxScrap = DEFAULT_MAX_SCRAP = 5
if (mScrap.get(viewType).mMaxScrap <= scrapHeap.size()) { // SparseArray<ScrapData> mScrap = new SparseArray<>();
return;
}
if (DEBUG && scrapHeap.contains(scrap)) {
throw new IllegalArgumentException("this scrap item already exists");
}
scrap.resetInternal();
scrapHeap.add(scrap);
}
复用tryGetViewHolderForPositionByDeadline()
getViewForPosition(int position)->getViewForPosition(position, false)->tryGetViewHolderForPositionByDeadline(position, dryRun, FOREVER_NS).itemView
ViewHolder tryGetViewHolderForPositionByDeadline(int position,
boolean dryRun, long deadlineNs) {
//……
mChangedScrap
// 0) If there is a changed scrap, try to find from there
if (mState.isPreLayout()) {
holder = getChangedScrapViewForPosition(position); // position/id -> mChangedScrap
fromScrapOrHiddenOrCache = holder != null;
}
position -> mAttachedScrap/mCachedView
// 1) Find by position from scrap/hidden list/cache
if (holder == null) {
// position -> mAttachedScrap/(mCachedView源码注释:Search in our first-level recycled view cache.)
holder = getScrapOrHiddenOrCachedHolderForPosition(position, dryRun);
if (holder != null) {
if (!validateViewHolderForOffsetPosition(holder)) { // 如果找到的ViewHolder不可用 -> 回收 -> RecycledViewPool
// recycle holder (and unscrap if relevant) since it can't be used
if (!dryRun) {
// ……省略回收前的一些处理
recycleViewHolderInternal(holder);
}
holder = null;
} else {
fromScrapOrHiddenOrCache = true;
}
}
}
if (holder == null) {
final int offsetPosition = mAdapterHelper.findPositionOffset(position);
// ……
final int type = mAdapter.getItemViewType(offsetPosition);
id -> mAttachedScrap/mCachedView
// 2) Find from scrap/cache via stable ids, if exists
if (mAdapter.hasStableIds()) {
// id -> mAttachedScrap/mCachedView
holder = getScrapOrCachedViewForId(mAdapter.getItemId(offsetPosition),
type, dryRun);
if (holder != null) {
// update position
holder.mPosition = offsetPosition;
fromScrapOrHiddenOrCache = true;
}
}
自定义缓存ViewCacheExtension
// 自定义缓存 `mViewCacheExtension != null`
if (holder == null && mViewCacheExtension != null) {
// We are NOT sending the offsetPosition because LayoutManager does not
// know it.
final View view = mViewCacheExtension
.getViewForPositionAndType(this, position, type);
if (view != null) {
holder = getChildViewHolder(view);
//……省略部分`holder == null`的异常处理
}
}
RecycledViewPool
- 注:默认每种类型
ViewType-> 缓存5个ViewHolder
// 从`RecycledViewPool`中找到对应类型的ViewHolder
if (holder == null) { // fallback to pool
//……省略调试代码块
holder = getRecycledViewPool().getRecycledView(type);
if (holder != null) {
holder.resetInternal();
if (FORCE_INVALIDATE_DISPLAY_LIST) {
invalidateDisplayListInt(holder);
}
}
}
onCreateViewHolder()
// 最终策略:onCreateViewHolder()
if (holder == null) {
//……
holder = mAdapter.createViewHolder(RecyclerView.this, type);
//……
}
项目onCreate和onBind方法调用次数统计
最后,是统计
onCreateViewHolder和onBindViewHolder方法调用次数,LogCat中打印的项目
userbiliy/RecyclerView: onCreateViewHolder和onBindViewHolder方法调用次数测试日志 (github.com)
- 注意:图片里的编号仅是个编号,与次序无关,具体次序看上下滑动顺序