RecyclerView源码分析

前言

RecyclerView是一个Android5.0推出的比ListView更强大的列表控件;可以实现更复杂的效果,同时它的解耦性也更好,分析起来比LIstView更复杂;

View的绘制过程

View的事件传递及分发

ListView的源码分析

先来看下RecyclerView中的内部类;主要有LayoutManager、Recycler(类似ListView的RecycleBin)、ViewHolder(ListView中常在Adapter中自定义,提高性能)、Adapter;

相关类的介绍

RecyclerView的Adapter类主要方法onCreateViewHolder()、onBindViewHolder();

public abstract static class Adapter<VH extends ViewHolder> {
    private final AdapterDataObservable mObservable = new AdapterDataObservable();
    private boolean mHasStableIds = false;
   
    public abstract VH onCreateViewHolder(ViewGroup parent, int viewType);
   
    public abstract void onBindViewHolder(VH holder, int position);
   
    public void onBindViewHolder(VH holder, int position, List<Object> payloads) {
        onBindViewHolder(holder, position);
    }
   
    public final VH createViewHolder(ViewGroup parent, int viewType) {
        final VH holder = onCreateViewHolder(parent, viewType);
        return holder;
    }

    public final void bindViewHolder(VH holder, int position) {
        holder.mPosition = position;
        onBindViewHolder(holder, position, holder.getUnmodifiedPayloads());
    }
}

RecyclerView的ViewHolder:描述Item View,避免多次重复findViewById();RecyclerView强制要求使用ViewHolder;

RecyclerView的Recycler 负责管理scrapped、detached的Item View,以供LayoutManager获取View为Adapter的数据集,在指定位置展示数据;作用和ListView的RecyclerBin都是用来缓存,方便复用的;但是Recycler缓存的是ViewHolder,而且缓存的方式更多,主要在tryGetViewHolderForPositionByDeadline()方法中可以看出获取缓存的ViewHolder的优先级;

public final class Recycler {
    //缓存ViewHolder的集合
    final ArrayList<ViewHolder> mAttachedScrap = new ArrayList<>();
    ArrayList<ViewHolder> mChangedScrap = null;

    final ArrayList<ViewHolder> mCachedViews = new ArrayList<ViewHolder>();

    private final List<ViewHolder>
            mUnmodifiableAttachedScrap = Collections.unmodifiableList(mAttachedScrap);

    private int mRequestedCacheMax = DEFAULT_CACHE_SIZE;
    int mViewCacheMax = DEFAULT_CACHE_SIZE;

    RecycledViewPool mRecyclerPool;

    private ViewCacheExtension mViewCacheExtension;

    static final int DEFAULT_CACHE_SIZE = 2;

    //获取给定位置初始化的View;
    public View getViewForPosition(int position) {
        return getViewForPosition(position, false);
    }

    View getViewForPosition(int position, boolean dryRun) {
        return tryGetViewHolderForPositionByDeadline(position, dryRun, FOREVER_NS).itemView;
    }

   //尝试从Recycler scrap、cache、RecycledViewPool或者直接创建给定position的ViewHolder;
    @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 (!validateViewHolderForOffsetPosition(holder)) {
                    // recycle holder (and unscrap if relevant) since it can't be used
                    holder = null;
                } else {
                    fromScrapOrHiddenOrCache = true;
                }
            }
        }
        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()) {
                holder = getScrapOrCachedViewForId(mAdapter.getItemId(offsetPosition),
                        type, dryRun);
                if (holder != null) {
                    // update position
                    holder.mPosition = offsetPosition;
                    fromScrapOrHiddenOrCache = true;
                }
            }
            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);
                }
            }
            if (holder == null) { // fallback to pool
                holder = getRecycledViewPool().getRecycledView(type);
                if (holder != null) {
                    holder.resetInternal();
                    if (FORCE_INVALIDATE_DISPLAY_LIST) {
                        invalidateDisplayListInt(holder);
                    }
                }
            }
            if (holder == null) {
                long start = getNanoTime();
                //主要看下,从Adapter的createViewHolder()创建一个ViewHoder;
                holder = mAdapter.createViewHolder(RecyclerView.this, type);
                if (ALLOW_THREAD_GAP_WORK) {
                    // only bother finding nested RV if prefetching
                    RecyclerView innerView = findNestedRecyclerView(holder.itemView);
                    if (innerView != null) {
                        holder.mNestedRecyclerView = new WeakReference<>(innerView);
                    }
                }
            }
        }
        
        boolean bound = false;
        if (mState.isPreLayout() && holder.isBound()) {
            // do not update unless we absolutely have to.
            holder.mPreLayoutPosition = position;
        } else if (!holder.isBound() || holder.needsUpdate() || holder.isInvalid()) {
            final int offsetPosition = mAdapterHelper.findPositionOffset(position);
            //尝试bind view;
            bound = tryBindViewHolderByDeadline(holder, offsetPosition, position, deadlineNs);
        }
        
        return holder;
    } 
    
    //尝试bind view;
    private boolean tryBindViewHolderByDeadline(ViewHolder holder, int offsetPosition,
        int position, long deadlineNs) {
        holder.mOwnerRecyclerView = RecyclerView.this;
        final int viewType = holder.getItemViewType();
        long startBindNs = getNanoTime();
        //调用Adapter的bindViewHolder()-->onBindViewHolder()有我们具体实现,填充内容;
        mAdapter.bindViewHolder(holder, offsetPosition);
       
        return true;
    }
}

主要看下直接创建一个ViewHolder,调用Adapter的createViewHolder()–>onCreateViewHolder()创建一个ViewHolder,具体实现由我们自己实现;然后调用bindViewHolder–>onBindViewHolder()填充具体数据;

RecyclerView的LayoutManager是RecyclerView非常重要的一块,主要负责Item View的Measure,Layout;决定不可见的Item View合适被回收;通过更改LayoutManager实现竖直滑动的列表(ListView)、网格列表(GridView)、瀑布流和横向滑动的列表等;由此可以看出RecyclerView的核心功能主要在LayoutManager

public abstract static class LayoutManager {
    ChildHelper mChildHelper;
    RecyclerView mRecyclerView;
    
    //必须由子类重写,layout所有的Item View
    public void onLayoutChildren(Recycler recycler, State state) {
    }
}

LinearLayoutManager:提供类似ListView的功能,可以实现横向、竖向的列表;重要的方法onLayoutChildren()功能类似于ListView的layoutChildren

//reverseLayout默认为false:表示从上往下layout ItemView;true表示从下往上layout ItemView(聊天列表);
public LinearLayoutManager(Context context, int orientation, boolean reverseLayout) {
    setOrientation(orientation);
    setReverseLayout(reverseLayout);
    setAutoMeasureEnabled(true);
}

LinearLayoutManagerLayoutState类:帮助类

static class LayoutState {

    static final int LAYOUT_START = -1;
    static final int LAYOUT_END = 1;
    
	//item View是否能够被回收
    boolean mRecycle = true;

    boolean hasMore(RecyclerView.State state) {
        return mCurrentPosition >= 0 && mCurrentPosition < state.getItemCount();
    }

 	//为下一个数据获取View;
    View next(RecyclerView.Recycler recycler) {
        if (mScrapList != null) {
            return nextViewFromScrapList();
        }
        final View view = recycler.getViewForPosition(mCurrentPosition);
        mCurrentPosition += mItemDirection;
        return view;
    }   
}

GridLayoutManager是LinearLayoutManager的子类,实现实现网格的效果;通过spanCount来实现一行N列;默认情况下spanCount为1;可以通过setSpanSizeLookup()方法动态改变每个position的spanSize;来实现一行一列、一行多列的混排,实现复杂列表;

public class GridLayoutManager extends LinearLayoutManager {
	//spanCount:表示将一列分为多少份;
    public GridLayoutManager(Context context, int spanCount, int orientation,
            boolean reverseLayout) {
        super(context, orientation, reverseLayout);
        setSpanCount(spanCount);
    }
}

动态改变每个position的spanSize;来实现一行一列、一行多列的混排,实现复杂列表

//spanCount:要取最小公倍数;将一行分为6列;
GridLayoutManager layoutManager = new GridLayoutManager(act, 6);
final int spanCount = layoutManager.getSpanCount();
//DefaultSpanSizeLookup类getSpanSize默认返回1;
layoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
    @Override
    public int getSpanSize(int position) {
        int spanSize = 0;
        if (position == 0 || position == 5) {
            spanSize = spanCount;//当前position的View占spanCount列,即一行一列
        } else if (position < 5) {
            spanSize = spanCount / 2;//一行两列
        } else {
            spanSize = spanCount / 3;//一行三列
        }
        return spanSize;
    }
});

StaggeredGridLayoutManager:用来实现瀑布流,spanCount设置一行N列;

public StaggeredGridLayoutManager(int spanCount, int orientation) {
    mOrientation = orientation;
    setSpanCount(spanCount);//
    setAutoMeasureEnabled(mGapStrategy != GAP_HANDLING_NONE);
    mLayoutState = new LayoutState();
    createOrientationHelpers();
}

初始化

以以下流程来分析;

LinearLayoutManager layoutManager = new LinearLayoutManager(act);
recyclerView.setLayoutManager(layoutManager);
NestScrollViewAdapter adapter = new NestScrollViewAdapter(null);
recyclerView.setAdapter(adapter);

RecyclerView的setLayoutManager();

public void setLayoutManager(LayoutManager layout) {
    mLayout = layout;
    if (layout != null) {
        mLayout.setRecyclerView(this);
        if (mIsAttached) {
            mLayout.dispatchAttachedToWindow(this);
        }
    }
    mRecycler.updateViewCacheSize();
    requestLayout();
}

RecyclerView的setAdapter()

public void setAdapter(Adapter adapter) {
    // bail out if layout is frozen
    setLayoutFrozen(false);
    setAdapterInternal(adapter, false, true);
    //调用onMeasure()、onLayout()、onDraw();
    requestLayout();
}

 private void setAdapterInternal(Adapter adapter, boolean 		        compatibleWithPrevious,  boolean removeAndRecycleViews) {
     
     mAdapterHelper.reset();
     final Adapter oldAdapter = mAdapter;
     mAdapter = adapter;
     //注册监听
     if (adapter != null) {
         adapter.registerAdapterDataObserver(mObserver);
         adapter.onAttachedToRecyclerView(this);
     }
 }

绘制过程

调用requestLayout()方法之后,会依次调用onMeasure()、onLayout()、onDraw();我们依次来分析;首先看RecyclerView的onMeasure()主要是调用dispatchLayoutStep1()、dispatchLayoutStep2()方法,其中dispatchLayoutStep2()方法最重要;

@Override
protected void onMeasure(int widthSpec, int heightSpec) {
    //在初始化LinearLayoutManager时就赋值为true;
    if (mLayout.mAutoMeasure) {
        final boolean skipMeasure = widthMode == MeasureSpec.EXACTLY
                    && heightMode == MeasureSpec.EXACTLY;
        mLayout.onMeasure(mRecycler, mState, widthSpec, heightSpec);
         //如果宽高的Mode都是EXACTLY(为match_parent或者是固定的值)或者Adapter= null就跳过
        if (skipMeasure || mAdapter == null) {
            return;
        }
        
        //State三种状态:STEP_START:默认状态、dispatchLayoutStep3()方法;
        //STEP_LAYOUT:dispatchLayoutStep1()方法;
        //STEP_ANIMATIONS;dispatchLayoutStep2()方法;
        if (mState.mLayoutStep == State.STEP_START) {
            dispatchLayoutStep1();
        }
        
        // set dimensions in 2nd step. Pre-layout should happen with old dimensions for
        // consistency
        mLayout.setMeasureSpecs(widthSpec, heightSpec);
        mState.mIsMeasuring = true;
        
        dispatchLayoutStep2();

        // now we can get the width and height from the children.
        mLayout.setMeasuredDimensionFromChildren(widthSpec, heightSpec);

        if (mLayout.shouldMeasureTwice()) {
        }
    } else {
       
    }
}

RecyclerView的dispatchLayoutStep1():layout的第一步;

private void dispatchLayoutStep1() {
    mState.mLayoutStep = State.STEP_LAYOUT;
}

RecyclerView的dispatchLayoutStep2():layout的第二步,最重要的地方;调用LayoutManager的onLayoutChildren()方法,子类重写具体的实现逻辑;在该方法中不断的创建或者复用ItemView来填充RecyclerView

private void dispatchLayoutStep2() {
    // Step 2: Run layout
    mState.mInPreLayout = false;
    mLayout.onLayoutChildren(mRecycler, mState);
    mState.mLayoutStep = State.STEP_ANIMATIONS;
}

1)以LinearlayoutManager的onLayoutChildren()为例,不断是从上往下(正序)还是从下往上(倒叙)layout children,都是调用fill()方法,主要是LayoutState中的参数不同;

@Override
public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
    ensureLayoutState();
    mLayoutState.mRecycle = false;
    // resolve layout direction
    resolveShouldLayoutReverse();
    
    //AnchorInfo用来保存信息,主要为mPosition赋值;默认情况下mValid=false;
    if (!mAnchorInfo.mValid || mPendingScrollPosition != NO_POSITION
        || mPendingSavedState != null) {
        mAnchorInfo.reset();
        mAnchorInfo.mLayoutFromEnd = mShouldReverseLayout ^ mStackFromEnd;
        updateAnchorInfoForLayout(recycler, state, mAnchorInfo);
        mAnchorInfo.mValid = true;
    }else if(){}
    
    //空方法,在GridLayoutManager中被重写;
    onAnchorReady(recycler, state, mAnchorInfo, firstLayoutDirection);
    //Recycler回收View;
    detachAndScrapAttachedViews(recycler);
   
    //根据LayoutState中的参数开始填充;
    fill(recycler, mLayoutState, state, false);
}

LinearLayoutManager的fill():通过调用layoutChunk()方法,根据LayoutState中的参数创建或者复用ItemView来填充;

int fill(RecyclerView.Recycler recycler, LayoutState layoutState,
        RecyclerView.State state, boolean stopOnFocusable) {
    
    while ((layoutState.mInfinite || remainingSpace > 0) && layoutState.hasMore(state)) {
        layoutChunk(recycler, state, layoutState, layoutChunkResult);
    }
    
    return start - layoutState.mAvailable;
}

LinearLayoutManager的layoutChunk();每次绘制一个ItemView,通过LayoutState类的next()方法获取Item View(不管是复用,还是重新创建)来填充RecyclerVIew;

void layoutChunk(RecyclerView.Recycler recycler, RecyclerView.State state,
        LayoutState layoutState, LayoutChunkResult result) {
    //LayoutState的next()方法主要是通过Recycler.getViewForPosition()获取一个View;
    View view = layoutState.next(recycler);
    if (view == null) {
        result.mFinished = true;
        return;
    }
	//主要调用addView()填充到RecyclerView中;
   addView(view);
}

LinearLayoutManager实现的是单行的列表,那RecyclerView是如何实现网格效果的呢?甚至实现一行一列和一行多列混排的效果?我们来看下GridLayoutManager;

2)以GridLayoutManager为例GridLayoutManager的onLayoutChildren()主要调用父类LinearLayoutManager的onLayoutChildren();

@Override
public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
    super.onLayoutChildren(recycler, state);
}

GridLayoutManager的onAnchorReady()在父类LinearLayoutManager的onLayoutChildren()中调用;

@Override
void onAnchorReady(RecyclerView.Recycler recycler, RecyclerView.State state,
                   AnchorInfo anchorInfo, int itemDirection) {
    super.onAnchorReady(recycler, state, anchorInfo, itemDirection);
    
    //最终调用calculateItemBorders(),根据mSpanCount和totalSpace(width-左右padding),计算每一span的右边界,并缓存在mCachedBorders数组中;
    updateMeasurements();
    if (state.getItemCount() > 0 && !state.isPreLayout()) {
        ensureAnchorIsInCorrectSpan(recycler, state, anchorInfo, itemDirection);
    }
    //创建一个长度为mSpanCount的数组mSet;
    ensureViewSet();
}

GridLayoutManager的layoutChunk():每次绘制一行,可能有多个ItemView,要根据position对应的View所占的spanSize来决定;

@Override
void layoutChunk(RecyclerView.Recycler recycler, RecyclerView.State state,
        LayoutState layoutState, LayoutChunkResult result) {
   
    int count = 0;
    int consumedSpanCount = 0;
    int remainingSpan = mSpanCount;
    
    while (count < mSpanCount && layoutState.hasMore(state) && remainingSpan > 0) {
        int pos = layoutState.mCurrentPosition;
        //根据position获取spanSize;
        final int spanSize = getSpanSize(recycler, state, pos);
        //remainingSpan不够当前pos的显示,就break,不填充View,空白;
        remainingSpan -= spanSize;
        if (remainingSpan < 0) {
            break; // item did not fit into this row or column
        }
        //根据pos获取当前ItemView
        View view = layoutState.next(recycler);
        if (view == null) {
            break;
        }
        consumedSpanCount += spanSize;
        //缓存Item View;
        mSet[count] = view;
        count++;
    }
	//如果一个ItemView都没有
    if (count == 0) {
        result.mFinished = true;
        return;
    }

    int maxSize = 0;
    float maxSizeInOther = 0; // use a float to get size per span

 
    for (int i = 0; i < count; i++) {
        View view = mSet[i];
        addView()//将ItemView 填充到RecyclerView中
            
        calculateItemDecorationsForChild(view, mDecorInsets);

        measureChild(view, otherDirSpecMode, false);
    }
    
    int left = 0, right = 0, top = 0, bottom = 0;
    //计算ItemView的左上右下值;
}

3)StaggeredGridLayoutManager实现瀑布流效果(当每个ItemView的高度都是一样的情况下就变成一般的网格了)具体是如何实现的,就自己了解下,大致过程基本一致;

其次,绘制的第二步onLayout()方法

@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
    TraceCompat.beginSection(TRACE_ON_LAYOUT_TAG);
    dispatchLayout();
    TraceCompat.endSection();
    mFirstLayoutComplete = true;
}

dispatchLayout():主要调用dispatchLayoutStep3(),前两部一般在onMeasure()中已经调用了;

void dispatchLayout() {
    mState.mIsMeasuring = false;
    //如果dispatchLayoutStep3()被调用了,mLayoutStep=STEP_START;
    if (mState.mLayoutStep == State.STEP_START) {
        dispatchLayoutStep1();
        mLayout.setExactMeasureSpecsFrom(this);
        dispatchLayoutStep2();
        
    } else if (mAdapterHelper.hasUpdates() || mLayout.getWidth() != getWidth()
            || mLayout.getHeight() != getHeight()) {
        // First 2 steps are done in onMeasure but looks like we have to run again due to
        // changed size.
        mLayout.setExactMeasureSpecsFrom(this);
        dispatchLayoutStep2();
    } else {
        // always make sure we sync them (to ensure mode is exact)
        mLayout.setExactMeasureSpecsFrom(this);
    }
    
    dispatchLayoutStep3();
}

滑动过程

dispatchNestedXXX()方法都是RecyclerView配合CoordinatorLayout使用的,具体可阅读CoordinatorLayout的源码分析了解相关方法的调用;

事件分发的三个主要方法:dispatchTouchEvent()、onInterceptTouchEvent()、onTouchEvent();RecyclerView重写了onInterceptTouchEvent()、onTouchEvent();

RecyclerView的onInterceptTouchEvent():判断在何时拦截事件让RecyclerView来消费;

@Override
public boolean onInterceptTouchEvent(MotionEvent e) {
    //如果recyclerView设置了addOnItemTouchListener监听,并且onInterceptTouchEvent()返回true;
    if (dispatchOnItemTouchIntercept(e)) {
        cancelTouch();
        return true;
    }

    switch (action) {
        case MotionEvent.ACTION_DOWN:
            if (mScrollState == SCROLL_STATE_SETTLING) {
                getParent().requestDisallowInterceptTouchEvent(true);
                setScrollState(SCROLL_STATE_DRAGGING);
            }
            break;
        case MotionEvent.ACTION_MOVE: {
            if (mScrollState != SCROLL_STATE_DRAGGING) {
                if (canScrollHorizontally && Math.abs(dx) > mTouchSlop) {
                    mLastTouchX = x;
                    startScroll = true;
                }
                if (canScrollVertically && Math.abs(dy) > mTouchSlop) {
                    mLastTouchY = y;
                    startScroll = true;
                }
                //可以滑动,改变scroll状态;
                if (startScroll) {
                    setScrollState(SCROLL_STATE_DRAGGING);
                }
            }
        } break;
    }
    return mScrollState == SCROLL_STATE_DRAGGING;
}

RecyclerView的onTouchEvent()

@Override
public boolean onTouchEvent(MotionEvent e) {
    //Recycle人View是否注册了addOnItemTouchListener监听;
    if (dispatchOnItemTouch(e)) {
        cancelTouch();
        return true;
    }

    switch (action) {
        case MotionEvent.ACTION_DOWN: {
           mInitialTouchX = mLastTouchX = (int) (e.getX() + 0.5f);
            mInitialTouchY = mLastTouchY = (int) (e.getY() + 0.5f);
        } break;

        case MotionEvent.ACTION_MOVE: {
            final int x = (int) (e.getX(index) + 0.5f);
            final int y = (int) (e.getY(index) + 0.5f);
            int dx = mLastTouchX - x;
            int dy = mLastTouchY - y;
			//如果mScrollState不是SCROLL_STATE_DRAGGING,并且可以滑动,并且在相同的方向上产生有效滑动,就setScrollState(SCROLL_STATE_DRAGGING);
            
            //如果是SCROLL_STATE_DRAGGING状态;在有消费滑动距离,就返回true;
            if (mScrollState == SCROLL_STATE_DRAGGING) {
                mLastTouchX = x - mScrollOffset[0];
                mLastTouchY = y - mScrollOffset[1];
				//有效滑动,让父类不要拦截事件;
                if (scrollByInternal(
                        canScrollHorizontally ? dx : 0,
                        canScrollVertically ? dy : 0,
                        vtev)) {
                    getParent().requestDisallowInterceptTouchEvent(true);
                }
            }
        } break;

        case MotionEvent.ACTION_UP: {
            //获取x方向、y方向的滑动速度,调用fling()方法;
            if (!((xvel != 0 || yvel != 0) && fling((int) xvel, (int) yvel))) {
                setScrollState(SCROLL_STATE_IDLE);
            }
            resetTouch();
        } break;
    }
    return true;
}

Move事件中的scrollByInternal():滑动RecyclerView,将滑出的Item View回收,同时创建或者复用ItemView来填充RecyclerView;

boolean scrollByInternal(int x, int y, MotionEvent ev) {
    int unconsumedX = 0, unconsumedY = 0;
    int consumedX = 0, consumedY = 0;
    
    if (mAdapter != null) {
        if (x != 0) {
            //调用LayoutManager的scrollHorizontallyBy()由子类重写;
            consumedX = mLayout.scrollHorizontallyBy(x, mRecycler, mState);
            unconsumedX = x - consumedX;
        }
        if (y != 0) {
            //调用LayoutManager的scrollVerticallyBy()由子类重写;
            consumedY = mLayout.scrollVerticallyBy(y, mRecycler, mState);
            unconsumedY = y - consumedY;
        }
    }
    
    if (consumedX != 0 || consumedY != 0) {
        //回调OnScrollListener的onScrolled()
        dispatchOnScrolled(consumedX, consumedY);
    }
   
    return consumedX != 0 || consumedY != 0;
}

以LinearLayoutManager为例,LinearLayoutManager的scrollVerticallyBy():调用scrollBy();

@Override
public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler,
        RecyclerView.State state) {
    if (mOrientation == HORIZONTAL) {
        return 0;
    }
    return scrollBy(dy, recycler, state);
}

LinearLayoutManager的scrollBy()主要调用fill():创建或者复用ItemView填充RecyclerView;和上面的OnMeasure()分析的一样;同时其他两种情况也类似;

int scrollBy(int dy, RecyclerView.Recycler recycler, RecyclerView.State state) {
   
    mLayoutState.mRecycle = true;
    //由RecyclerView的onTouchEvent()可知,dy>0,手指向上滑动;
    final int layoutDirection = dy > 0 ? LayoutState.LAYOUT_END : LayoutState.LAYOUT_START;
    final int absDy = Math.abs(dy);
    updateLayoutState(layoutDirection, absDy, true, state);
    final int consumed = mLayoutState.mScrollingOffset
            + fill(recycler, mLayoutState, state, false);
    if (consumed < 0) {
        return 0;
    }
    final int scrolled = absDy > consumed ? layoutDirection * consumed : dy;
    mOrientationHelper.offsetChildren(-scrolled);
    mLayoutState.mLastScrollDelta = scrolled;
    return scrolled;
}

UP事件中的fling()方法

public boolean fling(int velocityX, int velocityY) {

    final boolean canScrollHorizontal = mLayout.canScrollHorizontally();
    final boolean canScrollVertical = mLayout.canScrollVertically();

	//默认情况下返回false;
    if (!dispatchNestedPreFling(velocityX, velocityY)) {
        final boolean canScroll = canScrollHorizontal || canScrollVertical;
        
        //实现OnFlingListener监听,并且onFling()返回true;
        if (mOnFlingListener != null && mOnFlingListener.onFling(velocityX, velocityY)) {
            return true;
        }

        //最后调用ViewFlinger的fling();
        if (canScroll) {
            velocityX = Math.max(-mMaxFlingVelocity, Math.min(velocityX, mMaxFlingVelocity));
            velocityY = Math.max(-mMaxFlingVelocity, Math.min(velocityY, mMaxFlingVelocity));
            mViewFlinger.fling(velocityX, velocityY);
            return true;
        }
    }
    return false;
}

ViewFlinger类是个Runnable;通过view.postDelayed();执行ViewFlinger的run()方法;有滑动距离,继续调用LayoutManager的scrollHorizontallyBy()或者scrollVerticallyBy();**和Move事件的scrollByInternal()**调用的过程一样;

class ViewFlinger implements Runnable {
 
    private OverScroller mScroller;
    Interpolator mInterpolator = sQuinticInterpolator;

    ViewFlinger() {
        //滑动类
        mScroller = new OverScroller(getContext(), sQuinticInterpolator);
    }

    @Override
    public void run() {
        final OverScroller scroller = mScroller;
        final SmoothScroller smoothScroller = mLayout.mSmoothScroller;
        
        if (scroller.computeScrollOffset()) {
           //滑动动画没有结束,就继续执行;
            if (mAdapter != null) {
                //调用LayoutManager中的scrollHorizontallyBy();
                if (dx != 0) {
                    hresult = mLayout.scrollHorizontallyBy(dx, mRecycler, mState);
                    overscrollX = dx - hresult;
                }
                ////调用LayoutManager中的scrollVerticallyBy();
                if (dy != 0) {
                    vresult = mLayout.scrollVerticallyBy(dy, mRecycler, mState);
                    overscrollY = dy - vresult;
                }
        }

    }
    
	//调用OVerScroller的fling();
    public void fling(int velocityX, int velocityY) {
        setScrollState(SCROLL_STATE_SETTLING);
        mLastFlingX = mLastFlingY = 0;
        mScroller.fling(0, 0, velocityX, velocityY,
                Integer.MIN_VALUE, Integer.MAX_VALUE, Integer.MIN_VALUE, Integer.MAX_VALUE);
        //最终调用view.postDelayed();执行ViewFlinger的run()方法;
        postOnAnimation();
    }
}

以上就是RecyclerView的整个过程的总体分析,如有问题,请多指教,谢谢!

发布了50 篇原创文章 · 获赞 7 · 访问量 3万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 精致技术 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览