View的绘制

onMeasure

开始,如果mLayout是空的,就会调用默认绘制方法

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
if (mLayout == null) {
        defaultOnMeasure(widthSpec, heightSpec);
        return;
    }

** 默认的绘制方法    
void defaultOnMeasure(int widthSpec, int heightSpec) {
    // 为RecyclerView测量最小大小
    final int width = LayoutManager.chooseSize(widthSpec,
            getPaddingLeft() + getPaddingRight(),
            ViewCompat.getMinimumWidth(this));
    final int height = LayoutManager.chooseSize(heightSpec,
            getPaddingTop() + getPaddingBottom(),
            ViewCompat.getMinimumHeight(this));

    setMeasuredDimension(width, height);
}

如果mLayout是自动测量,让mLayout进行测量,然后根据mState.mLayoutStep的状态进行是否 dispatchLayoutStep1(),接着dispatchLayoutStep2()等

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
if (mLayout.mAutoMeasure) {
        ...
        // 让LayoutManager负责测量 ,默认的方法是defaultOnMeasure,也可自己重写
        mLayout.onMeasure(mRecycler, mState, widthSpec, heightSpec);
        if (skipMeasure || mAdapter == null) {
            return;
        }
        // mState.mLayoutStep 是负责对应几个状态,一般状态STEP_START,需要dispatchLayoutStep1()
        if (mState.mLayoutStep == State.STEP_START) {
            dispatchLayoutStep1();
        }
        // 值得注意的是,setMeasureSpecs这个方法是放在dispatchLayoutStep1()后面,然后才开始真正测量大小
        mLayout.setMeasureSpecs(widthSpec, heightSpec);
        // 测量完毕,修改状态为true
        mState.mIsMeasuring = true; 
        dispatchLayoutStep2();
        // 测量子类大小,
        mLayout.setMeasuredDimensionFromChildren(widthSpec, heightSpec);
        // 如果需要进行两次测量
        if (mLayout.shouldMeasureTwice()) {
            继续重新测量自己大小和子类大小
            ...
        }
    } else {
      ...

如果不是自动测量

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
    // 这里注意 如果设置了hasFixedSize,直接mLayout.onMeasure(mRecycler, mState, widthSpec, heightSpec),然后返回
    // 就不在需要考虑adapter个别item的改变,onItemRangeChanged
    if (mHasFixedSize) {
            mLayout.onMeasure(mRecycler, mState, widthSpec, heightSpec);
            return;
        }
        // 如果是执行了onItemRangeChanged,onItemRangeInserted等针对一个item的监听会触发
        // 主要是针对adapter
        if (mAdapterUpdateDuringMeasure) {
            eatRequestLayout();
            onEnterLayoutOrScroll();
            processAdapterUpdatesAndSetAnimationFlags();
            onExitLayoutOrScroll();
            ...
        mLayout.onMeasure(mRecycler, mState, widthSpec, heightSpec);
        resumeRequestLayout(false);
        mState.mInPreLayout = false; // clear
    }

大致分析整个Measure流程,最主要的还是mLayout.onMeasure(mRecycler, mState, widthSpec, heightSpec);还是交给了mLayout进行测量

onLayout

onLayout里主要是分为了三个步骤,分别是dispatchLayoutStep1(),dispatchLayoutStep2(),dispatchLayoutStep3();

mState.mLayoutStep有三种状态,分别是:STEP_START,STEP_LAYOUT,STEP_ANIMATIONS

mLayout.setExactMeasureSpecsFrom(this); 这个是都执行了,作用是把RecyclerView的宽,高都设置为了MeasureSpec.EXACTLY模式

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
mState.mIsMeasuring = false;
    if (mState.mLayoutStep == State.STEP_START) { // 如果还是STEP_START,那就先dispatchLayoutStep1()
        dispatchLayoutStep1();
        mLayout.setExactMeasureSpecsFrom(this);
        dispatchLayoutStep2();
    } else if (mAdapterHelper.hasUpdates() || mLayout.getWidth() != getWidth()
            || mLayout.getHeight() != getHeight()) {
        // 已经重新有测量过
        mLayout.setExactMeasureSpecsFrom(this);
        dispatchLayoutStep2();
    } else {
        mLayout.setExactMeasureSpecsFrom(this);
    }
    dispatchLayoutStep3();

dispatchLayoutStep1()

里面十分复杂,根据注释结合理解,主要作用是对Adapter进行更新,计算保存item的动画信息,绝对哪个动画要执行,并且不断调整mState的信息,

里面有个重要的方法,processAdapterUpdatesAndSetAnimationFlags,最主要目的是处理item动画

processAdapterUpdatesAndSetAnimationFlags()方法

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
private void processAdapterUpdatesAndSetAnimationFlags() {
        if (mDataSetHasChangedAfterLayout) { // 是否有重新设置过数据,比如notofydatasetCHange
            // 所以我们要重新reset,
            // AdapterHelper.reset 主要是 记录UpdateOp的list全部reset掉
            // UpdateOp 是来处理跟踪item相关操作的
            mAdapterHelper.reset();
            mLayout.onItemsChanged(this);
        }
        //是否支持预期动画
        if (predictiveItemAnimationsEnabled()) {
            mAdapterHelper.preProcess();
        } else {
            mAdapterHelper.consumeUpdatesInOnePass();
        }

        //mRunSimpleAnimations 为true
        //1.mFirstLayoutComplete为true(onLayout第一次执行完后被置为true)
        //2.mItemAnimator不为空
        //3.Layout后数据发生了变化 或 有item被移除或添加 或 LayoutManager请求执行simple animations
        //4.Layout后数据不发生变化 或 mAdapter有稳定的ID

        boolean animationTypeSupported = mItemsAddedOrRemoved || mItemsChanged;
        mState.mRunSimpleAnimations = mFirstLayoutComplete
                && mItemAnimator != null
                && (mDataSetHasChangedAfterLayout
                || animationTypeSupported
                || mLayout.mRequestedSimpleAnimations)
                && (!mDataSetHasChangedAfterLayout
                || mAdapter.hasStableIds());

         //mRunPredictiveAnimations 为true
       // 1.mRunSimpleAnimations为true
         // 2.有item添加或移除
         // 3.Layout后数据未发生变化
         // 4.预期Item动画被开启       

        mState.mRunPredictiveAnimations = mState.mRunSimpleAnimations
                && animationTypeSupported
                && !mDataSetHasChangedAfterLayout
                && predictiveItemAnimationsEnabled();
    }

dispatchLayoutStep1() 大致就是帮助我们处理adapter更新,确定执行动画,保存view的信息等

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
 private void dispatchLayoutStep1() {
    清除mViewInfoStore的信息,如果还在滑动,记录滑动的信息到mState等等
    ...
    // 这个方法比较重要
    processAdapterUpdatesAndSetAnimationFlags();
   ...
   // 确定第一个和最后一个view的位置信息
    findMinMaxChildLayoutPositions(mMinMaxLayoutPositions);

    // 如果要执行simple动画就
    if (mState.mRunSimpleAnimations) {
        .... 获取对应的信息并且添加到mViewInfoStore中
           final ItemHolderInfo animationInfo = mItemAnimator
                    .recordPreLayoutInformation(mState, holder,
                            ItemAnimator.buildAdapterChangeFlagsForAnimations(holder),
                            holder.getUnmodifiedPayloads());
            mViewInfoStore.addToPreLayout(holder, animationInfo);
        ...
                mViewInfoStore.addToOldChangeHolders(key, holder);
            }
        }
    }
    if (mState.mRunPredictiveAnimations) {
      ... 同上,如果要
         // 这里会再次调用onLayoutChildren方法
          mLayout.onLayoutChildren(mRecycler, mState);
        }
        // we don't process disappearing list because they may re-appear in post layout pass.
        clearOldPositions();
    } else {
        clearOldPositions();
    }
    onExitLayoutOrScroll();
    resumeRequestLayout(false);
    mState.mLayoutStep = State.STEP_LAYOUT;
}

最后把mState的状态改为STEP_LAYOUT,可以说是绘制Layout前的准备

### dispatchLayoutStep2

该方法开始 mLayout.onLayoutChildren(mRecycler, mState); 方法进行布局

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
private void dispatchLayoutStep2() {
    // 进入布局
    eatRequestLayout();
    onEnterLayoutOrScroll();
    mState.assertLayoutStep(State.STEP_LAYOUT | State.STEP_ANIMATIONS);
    // 跳过预期动画的处理
    mAdapterHelper.consumeUpdatesInOnePass();
    mState.mItemCount = mAdapter.getItemCount();
    mState.mDeletedInvisibleItemCountSincePreviousLayout = 0;

    // 开始调用 mLayout.onLayoutChildren(mRecycler, mState); 方法进行布局
    mState.mInPreLayout = false;
    mLayout.onLayoutChildren(mRecycler, mState);

    mState.mStructureChanged = false;
    mPendingSavedState = null;

    //最后把状态修改为State.STEP_ANIMATIONS;
    mState.mLayoutStep = State.STEP_ANIMATIONS;
    onExitLayoutOrScroll();
    resumeRequestLayout(false);
    }

### dispatchLayoutStep3

这方法主要是进行动画的处理

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
    private void dispatchLayoutStep3() {
    // 进入布局阶段,并且修改为State.STEP_START
    mState.assertLayoutStep(State.STEP_ANIMATIONS);
    eatRequestLayout();
    onEnterLayoutOrScroll();
    mState.mLayoutStep = State.STEP_START;
    if (mState.mRunSimpleAnimations) {
        // 开始执行每个view的信息检查,是否要处理动画
        for (int i = mChildHelper.getChildCount() - 1; i >= 0; i--) {
            ... 找到ItemHolderInfo 保存了view的信息
            final ItemHolderInfo animationInfo = mItemAnimator
                    .recordPostLayoutInformation(mState, holder);
            // 旧的view的信息        
            ViewHolder oldChangeViewHolder = mViewInfoStore.getFromOldChangeHolders(key);
            if (oldChangeViewHolder != null && !oldChangeViewHolder.shouldIgnore()) {
                final boolean oldDisappearing = mViewInfoStore.isDisappearing(
                        oldChangeViewHolder);
                final boolean newDisappearing = mViewInfoStore.isDisappearing(holder);
                // 如果之前的view信息是消失了,不需要进行动画处理
                if (oldDisappearing && oldChangeViewHolder == holder) {
                    mViewInfoStore.addToPostLayout(holder, animationInfo);
                } else {
                    // 否则得到之前的ItemHolderInfo 
                    final ItemHolderInfo preInfo = mViewInfoStore.popFromPreLayout(
                            oldChangeViewHolder);
                    mViewInfoStore.addToPostLayout(holder, animationInfo);
                    ItemHolderInfo postInfo = mViewInfoStore.popFromPostLayout(holder);
                    if (preInfo == null) {
                        // 如果之前的preInfo为空
                        handleMissingPreInfoForChangeError(key, holder, oldChangeViewHolder);
                    } else {
                        // 不为空的话,动画处理
                        animateChange(oldChangeViewHolder, holder, preInfo, postInfo,
                                oldDisappearing, newDisappearing);
                    }
                }
            ...
        }

        mViewInfoStore.process(mViewInfoProcessCallback);
    }
    一系列收尾工作
    ...

简单分析了解了onLayout的流程,可以看出最主要的布局还是交给了mLayout去执行,当然里面还有有细节需要另外分析。

onDraw

主要还是我们平时一些分割线的绘制回调

draw

主要还是调用了mItemDecorations中的onDrawOver方法

1
2
3
4
5
6
7
8
9
    final int count = mItemDecorations.size();
    for (int i = 0; i < count; i++) {
        // 调用了mItemDecorations中的onDrawOver方法
        mItemDecorations.get(i).onDrawOver(c, this, mState);
    }
   ... 中间部分是 滑动到左边右边上边下边时候的EdgeEffect
    if (needsInvalidate) {
        ViewCompat.postInvalidateOnAnimation(this);
    }

onDraw

主要还是调用了mItemDecorations中的onDraw方法 @Override public void onDraw(Canvas c) { super.onDraw©;

1
2
3
4
5
    final int count = mItemDecorations.size();
    for (int i = 0; i < count; i++) {
        mItemDecorations.get(i).onDraw(c, this, mState);
    }
}

LinearLayoutManager

从之前的onLayout三步骤去分析:

dispatchLayoutStep1

如果是允许预期动画了,此时会调用mLayout.onLayoutChildren(mRecycler, mState);

然后dispatchLayoutStep1完后 会调用mLayout.setExactMeasureSpecsFrom(this); 确定大小

1
2
3
4
5
6
7
...
    if (mState.mRunPredictiveAnimations) {
   ...
        mLayout.onLayoutChildren(mRecycler, mState);
        mState.mStructureChanged = didStructureChange;
    ...
}

dispatchLayoutStep2

1
2
3
4
5
6
7
private void dispatchLayoutStep2() {
 ...
    // Step 2: Run layout
    mState.mInPreLayout = false;
    mLayout.onLayoutChildren(mRecycler, mState);
...
}

dispatchLayoutStep3

步骤3的时候 removeAndRecycleScrapInt,最后onLayoutCompleted

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
private void dispatchLayoutStep3() {
   ... 
    mLayout.removeAndRecycleScrapInt(mRecycler);
    ...
    mLayout.mRequestedSimpleAnimations = false;
      ... 
    //初始预取扩展了缓存,因此重置到下一个预取。
    //这防止初始预取永久地扩展高速缓存。
    if (mLayout.mPrefetchMaxObservedInInitialPrefetch) {
        mLayout.mPrefetchMaxCountObserved = 0;
        mLayout.mPrefetchMaxObservedInInitialPrefetch = false;
        mRecycler.updateViewCacheSize();
    }

    mLayout.onLayoutCompleted(mState);
    ... 

onLayoutChildren(mRecycler, mState)

核心方法,计算mAnchorInfo,判断mAnchorInfo.mLayoutFromEnd方向,执行对应的fling方法,最后还要重新检查更新那些位置有差距,进行修补

关于fling方法,调用layoutChunk方法,里面view的添加,位置摆放全放在里面

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
@Override
public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
   ... 重置mAnchorInfo的属性,并且重新设置mAnchorInfo
   // detachAndScrapAttachedViews方法回调了recyclerview中的scrapOrRecycleView方法
    detachAndScrapAttachedViews(recycler);
    mLayoutState.mInfinite = resolveIsInfinite();
    mLayoutState.mIsPreLayout = state.isPreLayout();
    if (mAnchorInfo.mLayoutFromEnd) { // 如果方向是start
     ...
    } else {// 如果方向是end,看一个就好
        // 更新mAnchorInfo状态
        // 分别想end方向,start方向,执行fling方法
        // 最后如果不够,mAvailable>0 我们还需要填充
        updateLayoutStateToFillEnd(mAnchorInfo);
        mLayoutState.mExtra = extraForEnd;
        fill(recycler, mLayoutState, state, false);
        endOffset = mLayoutState.mOffset;
        final int lastElement = mLayoutState.mCurrentPosition;
        if (mLayoutState.mAvailable > 0) {
            extraForStart += mLayoutState.mAvailable;
        }
        // fill towards start
        updateLayoutStateToFillStart(mAnchorInfo);
        mLayoutState.mExtra = extraForStart;
        mLayoutState.mCurrentPosition += mLayoutState.mItemDirection;
        fill(recycler, mLayoutState, state, false);
        startOffset = mLayoutState.mOffset;

        if (mLayoutState.mAvailable > 0) {
            extraForEnd = mLayoutState.mAvailable;
            // start could not consume all it should. add more items towards end
            updateLayoutStateToFillEnd(lastElement, endOffset);
            mLayoutState.mExtra = extraForEnd;
            fill(recycler, mLayoutState, state, false);
            endOffset = mLayoutState.mOffset;
        }
    }


    // 最后还要重新检查更新那些位置有差距,进行修补
    if (getChildCount() > 0) {
        // because layout from end may be changed by scroll to position
        // we re-calculate it.
        // find which side we should check for gaps.
        if (mShouldReverseLayout ^ mStackFromEnd) {
            int fixOffset = fixLayoutEndGap(endOffset, recycler, state, true);
            startOffset += fixOffset;
            endOffset += fixOffset;
            fixOffset = fixLayoutStartGap(startOffset, recycler, state, false);
            startOffset += fixOffset;
            endOffset += fixOffset;
        } else {
            int fixOffset = fixLayoutStartGap(startOffset, recycler, state, true);
            startOffset += fixOffset;
            endOffset += fixOffset;
            fixOffset = fixLayoutEndGap(endOffset, recycler, state, false);
            startOffset += fixOffset;
            endOffset += fixOffset;
        }
    }
    // 执行了预期动画
    layoutForPredictiveAnimations(recycler, state, startOffset, endOffset);
    ...
}

这里不详细去跟,至于findLastCompletelyVisibleItemPosition等方法是 根据ViewBoundsCheck类中的findOneViewWithinBoundFlags方法去匹配,初始化是在RecyclerVIew上

## Recycler

核心类,整个回收机制都在这个类上

### recycleView

首先是调用scrapOrRecycleView进行mAttachedScrap或者是mChangedScrap的缓存

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
    private void scrapOrRecycleView(Recycler recycler, int index, View view) {
        ...
        判断可以看到如果是viewHolder初始化没有真正移除,mAdapter没有hasStableIds()
        内部缓存recycleViewHolderInternal(viewHolder)
        否则 scrapView 缓存 
        detachViewAt 然后回收该view
        if (viewHolder.isInvalid() && !viewHolder.isRemoved()
                && !mRecyclerView.mAdapter.hasStableIds()) {
            removeViewAt(index);
            recycler.recycleViewHolderInternal(viewHolder);
        } else {
            detachViewAt(index);
            recycler.scrapView(view);
            mRecyclerView.mViewInfoStore.onViewDetached(viewHolder);
        }
    }

scrapView

该方法也是通过一系列的判断是 mAttachedScrap.add(holder); 还是 mChangedScrap.add(holder);

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
void scrapView(View 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);
        } else {
            if (mChangedScrap == null) {
                mChangedScrap = new ArrayList<ViewHolder>();
            }
            holder.setScrapContainer(this, true);
            mChangedScrap.add(holder);
        }
    }

然后cache缓存一个viwe的时候可以调用 public void recycleView(View view) 方法

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
public void recycleView(View view) {
        // This public recycle method tries to make view recycle-able since layout manager
        // intended to recycle this view (e.g. even if it is in scrap or change cache)
        ViewHolder holder = getChildViewHolderInt(view);
        if (holder.isTmpDetached()) {
            removeDetachedView(view, false);
        }
        if (holder.isScrap()) {
            holder.unScrap();
        } else if (holder.wasReturnedFromScrap()) {
            holder.clearReturnedFromScrapFlag();
        }
        recycleViewHolderInternal(holder);
    }

关键是调用了recycleViewHolderInternal(holder);

### recycleViewHolderInternal

该方法是recycler如何缓存viewholder的

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
     void recycleViewHolderInternal(ViewHolder holder) {
       开始对holder进行一些判断,如果不满足 抛出异常
       ... 
        if (forceRecycle || holder.isRecyclable()) { // 如果强行recycle或者允许recycyle
         // 如果mViewCacheMax大于0
            if (mViewCacheMax > 0
                    && !holder.hasAnyOfTheFlags(ViewHolder.FLAG_INVALID
                    | ViewHolder.FLAG_REMOVED
                    | ViewHolder.FLAG_UPDATE
                    | ViewHolder.FLAG_ADAPTER_POSITION_UNKNOWN)) {
                // 如果缓存的view的数量大于了最大值,就把第一个给移除,添加到pool中
                int cachedViewSize = mCachedViews.size();
                if (cachedViewSize >= mViewCacheMax && cachedViewSize > 0) {
                    recycleCachedViewAt(0);
                    cachedViewSize--;
                }

                int targetCacheIndex = cachedViewSize;
                ...
                这里会找到targetCacheIndex
                   targetCacheIndex = cacheIndex + 1;
                ... 
                最终添加到cacheview中
                mCachedViews.add(targetCacheIndex, holder);
                cached = true; 说明已经缓存过
            }
            if (!cached) { 没有缓存过 就加到
                addViewHolderToRecycledViewPool(holder, true);
                recycled = true;
            }
        } else {

        }
    }

### recycleCachedViewAt

将cacheview的移除,放到pool那里去

1
2
3
4
    ...
        addViewHolderToRecycledViewPool(viewHolder, true);
        mCachedViews.remove(cachedViewIndex);、
    ...

### tryGetViewHolderForPositionByDeadline

获取ViewHolder的时候会调用tryGetViewHolderForPositionByDeadline方法

getChangedScrapViewForPosition方法是获取mChangedScrap里面的holder

getScrapOrHiddenOrCachedHolderForPosition方法是获取mAttachedScrap里面的holder

RecyclerPool 通过mScrapHeap缓存,默认缓存5个

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
ViewHolder tryGetViewHolderForPositionByDeadline(int position,
            boolean dryRun, long deadlineNs) {
      ...
      如果是mState的状态是准备layout,通过chagngeview获取holder
        if (mState.isPreLayout()) {
        // 从mChangedScrap里面的holder
            holder = getChangedScrapViewForPosition(position);
            fromScrapOrHiddenOrCache = holder != null;
        }
        // holder依然是空
        if (holder == null) {
            // 通过pos,mAttachedScrap里面的holder,没有继续根据mCachedViews中的
            holder = getScrapOrHiddenOrCachedHolderForPosition(position, dryRun);
            // 如果holder不是空
            if (holder != null) {
                // 检测该holder是否可用
                if (!validateViewHolderForOffsetPosition(holder)) {
               ...
               可用缓存起来
               ...
                } else {
                    fromScrapOrHiddenOrCache = true;
                }
            }
        }
        // 如果holder还是空
        if (holder == null) {
         ...
            if (mAdapter.hasStableIds()) {
               // 通过 stable id 先从mAttachedScrap ,然后再从mCachedViews
                holder = getScrapOrCachedViewForId(mAdapter.getItemId(offsetPosition),
                        type, dryRun);
              ...
            if (holder == null && mViewCacheExtension != null) {
                final View view = mViewCacheExtension
                        .getViewForPositionAndType(this, position, type);
                if (view != null) {
                    // 从mViewCacheExtension获取view,如果view不为空,在从里面获取holder
                    holder = getChildViewHolder(view);
                    if (holder == null) { // 需要注意如果view不为空,holder空了 会报错
                        throw new IllegalArgumentException("getViewForPositionAndType returned"
                                + " a view which does not have a ViewHolder"
                                + exceptionLabel());
                 ...
            if (holder == null) { // fallback to pool
                ... 如果还是空,从pool中获取holder
                holder = getRecycledViewPool().getRecycledView(type);
           ...
            }
            if (holder == null) {
          ... 最后才调用createViewHolder方法去createHolder
                holder = mAdapter.createViewHolder(RecyclerView.this, type);
          ....
        return holder;
    }

大致总结:首先是判断mState的状态,如果是isPreLayout()则从mChangeSrap根据pos获取,然后是1级缓存mAttachScrap 通过pos获取,mCacheView 通过pos获取,接着,根据adapter stable id 获取,然后mViewCacheExtension获取view中的holder,最后才从pool中获取,没有就createHolder