前言
RecyclerView是一个Android5.0推出的比ListView更强大的列表控件;可以实现更复杂的效果,同时它的解耦性也更好,分析起来比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);
}
LinearLayoutManager的LayoutState类:帮助类
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的整个过程的总体分析,如有问题,请多指教,谢谢!