美文网首页
View系列->RecyclerView

View系列->RecyclerView

作者: 冉桓彬 | 来源:发表于2019-06-09 15:21 被阅读0次

RecyclerView源码太复杂了, 这里目前想只记住结论哈.
RecyclerView中ViewHolder或者View的缓存是通过Recycler实现的.

public final class Recycler {
    // 一级缓存
    final ArrayList<ViewHolder> mAttachedScrap = new ArrayList<>();
    ArrayList<ViewHolder> mChangedScrap = null;
    // 二级缓存
    final ArrayList<ViewHolder> mCachedViews = new ArrayList<ViewHolder>();
    private int mRequestedCacheMax = DEFAULT_CACHE_SIZE;
    int mViewCacheMax = DEFAULT_CACHE_SIZE;
    // 四级缓存
    RecycledViewPool mRecyclerPool;
    // 三级缓存
    private ViewCacheExtension mViewCacheExtension;
    static final int DEFAULT_CACHE_SIZE = 2;
}


上面这个流程图与下面的代码有关

@Nullable
ViewHolder tryGetViewHolderForPositionByDeadline(int position, boolean dryRun, long deadlineNs) {
    boolean fromScrapOrHiddenOrCache = false;
    ViewHolder holder = null;
    // 0) If there is a changed scrap, try to find from there
    if (mState.isPreLayout()) {
        holder = getChangedScrapViewForPosition(position);
        fromScrapOrHiddenOrCache = holder != null;
    }
    // 1) Find by position from scrap/hidden list/cache
    if (holder == null) {
        holder = getScrapOrHiddenOrCachedHolderForPosition(position, dryRun);
        if (holder != null) {
            ...
        }
    }
    if (holder == null) {
        final int offsetPosition = mAdapterHelper.findPositionOffset(position);
        final int type = mAdapter.getItemViewType(offsetPosition);
        // 2) Find from scrap/cache via stable ids, if exists
        if (mAdapter.hasStableIds()) {
            // 从mCachedViews中获取缓存的ViewHolder
            holder = getScrapOrCachedViewForId(mAdapter.getItemId(offsetPosition),
                            type, dryRun);
            if (holder != null) {
                // update position
                holder.mPosition = offsetPosition;
                fromScrapOrHiddenOrCache = true;
            }
        }
        if (holder == null) { // fallback to pool
            // 根据Type从RecyclerPool中获取ViewHolder
            holder = getRecycledViewPool().getRecycledView(type);
            if (holder != null) {
                // 获取ViewHolder之后, 调用这里将ViewHolder中的状态进行重置;
                holder.resetInternal();
            }
        }
        if (holder == null) {
            // 如果没有找到缓存的ViewHolder, 则新建ViewHolder, 新建ViewHolder时会设置对应的type
            holder = mAdapter.createViewHolder(RecyclerView.this, type);
        }
    }
    boolean bound = false;
    if (mState.isPreLayout() && holder.isBound()) {
        // do not update unless we absolutely have to.
        holder.mPreLayoutPosition = position;
    // 新建ViewHolder或者ViewHolder.resetInternal之后, mFlags被置为0, 然后进入if语句
    // 通过tryBindViewHolderByDeadline最终触发onBindViewHolder()的执行.
    } else if (!holder.isBound() || holder.needsUpdate() || holder.isInvalid()) {
        final int offsetPosition = mAdapterHelper.findPositionOffset(position);
        // 这里最终会触发Adapter.onBindViewHolder的执行
        bound = tryBindViewHolderByDeadline(holder, offsetPosition, position, deadlineNs);
    }
    return holder;
}
ViewHolder.resetInternal
void resetInternal() {
    mFlags = 0;
}
boolean isInvalid() {
    return (mFlags & FLAG_INVALID) != 0;
}
boolean needsUpdate() {
    return (mFlags & FLAG_UPDATE) != 0;
}

boolean isBound() {
    return (mFlags & FLAG_BOUND) != 0;
}

参考文章:
https://zhuanlan.zhihu.com/p/23339185
https://www.jianshu.com/p/e44961f8add5

相关文章

网友评论

      本文标题:View系列->RecyclerView

      本文链接:https://www.haomeiwen.com/subject/pjknxctx.html