图解RecycleView的复用机制

135 阅读1分钟

image.png

  • 先找入口,recycleview只有一个地方调用了addView,全局搜索:
    • RecyclerView.this.addView(child, index);
  • 往上搜寻:
    • ChildHelper.addView()
    • LayoutManager.addViewInt()
    • LayoutManager.addView()
    • LinearLayoutManager.layoutChunk()
  • 找到关键节点,往下搜寻,LinearLayoutManager.layoutChunk()中:
    • layoutState.next(recycler)
    • recycler.getViewForPosition(mCurrentPosition)
    • 最终找到这个方法
    • ViewHolder tryGetViewHolderForPositionByDeadline(int position,boolean dryRun, long deadlineNs)
ViewHolder tryGetViewHolderForPositionByDeadline(int position,boolean dryRun, long deadlineNs) {
    ...
    // 0) If there is a changed scrap, try to find from there
    if (mState.isPreLayout()) {
        /**
         * 1.特殊情况:isPreLayout()预布局
         * 从 changeScrap 获取
         */
        holder = getChangedScrapViewForPosition(position);
        ...
    }
    // 1) Find by position from scrap/hidden list/cache
    if (holder == null) {
        /**
         * 2.从废料、隐藏View、缓存中获取
         * mAttachedScrap『ArrayList<VH>』
         * mHiddenViews『ArrayList<View>』
         * mCachedViews『ArrayList<VH>』
         */
        holder = getScrapOrHiddenOrCachedHolderForPosition(position, dryRun);
        ...
    }
    if (holder == null) {
        ...
        // 2) Find from scrap/cache via stable ids, if exists
        if (mAdapter.hasStableIds()) {
            /**
             * 3.特殊情况:当adapter设置了id,和2一样,2是用的position
             */
            holder = getScrapOrCachedViewForId(mAdapter.getItemId(offsetPosition), type, dryRun);
            ...
        }
        if (holder == null && mViewCacheExtension != null) {
            // We are NOT sending the offsetPosition because LayoutManager does not
            // know it.
            /**
             * 4.特殊情况:用户自定义缓存
             * ViewCacheExtension
             */
            final View view = mViewCacheExtension.getViewForPositionAndType(this, position, type);
            if (view != null) {
                holder = getChildViewHolder(view);
                ...
            }
        }
        if (holder == null) { // fallback to pool
           ...
            /**
             * 5.从回收池获取:RecycleViewPool『ArrayList<ViewHolder>』
             */
            holder = getRecycledViewPool().getRecycledView(type);
            ...
        }
        if (holder == null) {
            /**
             * 6.不走回收,直接创建
             */
            holder = mAdapter.createViewHolder(RecyclerView.this, type);
            ...
        }
    }
        ...
    return holder;
}

细节内容分析推荐:juejin.cn/post/684490…