recyclerview多种item item为什么是整屏高

RecyclerView的使用与深入分析
RecyclerView的使用与深入分析
Android源码
RecyclerView中的域
private Adapter mA//与RecyclerView绑定的Adapter
@VisibleForTesting LayoutManager mL //与RecyclerView绑定的LayoutManager
private final ArrayList&ItemDecoration& mItemDecorations = new ArrayList&&(); //存储所有装饰对象
ItemAnimator mItemAnimator = new DefaultItemAnimator(); //删除、插入、添加等操作对应显示的动画
//OnScrollListener定义了onScrolled和onScrollStateChanged方法
private OnScrollListener mScrollL
//监听器 对应setOnScrollListener方法,该方法已经标注为已过时
private List&OnScrollListener& mScrollL//监听器 对应addOnScrollListener方法
private final RecyclerViewDataObserver mObserver = new RecyclerViewDataObserver();
//调用Adapter的notifyDataXXX()方法,实际上是在调用 mObserver的对应方法,作用就是从Adapter取出更新的数据
final Recycler mRecycler = new Recycler();//管理RecyclerView暂时不使用的ViewHolder对象
private final ViewFlinger mViewFlinger = new ViewFlinger();//实现根据用户滑动的动作惯性的继续执行一段滑动,
addItemDecoration()@RecyclerView.class
public void addItemDecoration(ItemDecoration decor) {
addItemDecoration(decor, -1);
addItemDecoration()@RecyclerView.class
public void addItemDecoration(ItemDecoration decor, int index) {
if (mLayout != null) { mLayout.assertNotInLayoutOrScroll(&Cannot add item decoration during a scroll
+ & layout&); } //如果当前Layout处于绘制状态会报错
if (index & 0) { mItemDecorations.add(decor);
} //末尾添加
else {mItemDecorations.add(index, decor);
}//指定位置添加
requestLayout();
requestLayout()@RecyclerView.class
public void requestLayout() {
if (mEatRequestLayout == 0 && !mLayoutFrozen) {
super.requestLayout(); }
mLayoutRequestEaten = }
该方法大体思路很简单就是将参数ItemDecoration decor存入集合ArrayList&ItemDecoration& mItemDecorations中。
setItemAnimator()@RecyclerView.class
public void setItemAnimator(ItemAnimator animator) {
if (mItemAnimator != null) { //
mItemAnimator.endAnimations();
mItemAnimator.setListener(null);
mItemAnimator =
if (mItemAnimator != null) {
mItemAnimator.setListener(mItemAnimatorListener); //note1
跟addItemDecoration()方法类似,只不过这里是更新ItemAnimator mItemAnimator域
public void setLayoutManager(LayoutManager layout) {
if (layout == mLayout) { }
stopScroll();
if (mLayout != null) { //第一次调用该语句为假
if (mIsAttached) {
mLayout.dispatchDetachedFromWindow(this, mRecycler);
mLayout.setRecyclerView(null);
mRecycler.clear(); //clear操作
mLayout = //更新mLayout域
if (layout != null) {
if (layout.mRecyclerView != null) { throw ....}
mLayout.setRecyclerView(this); //LayoutManager和当前RecyclerView对象
if (mIsAttached) {
mLayout.dispatchAttachedToWindow(this);
requestLayout(); //重绘
public void setAdapter(Adapter adapter) {
setLayoutFrozen(false);
setAdapterInternal(adapter, false, true);
requestLayout(); //重绘
setAdapterInternal()@RecyclerView.class
private void setAdapterInternal(Adapter adapter, boolean compatibleWithPrevious, boolean removeAndRecycleViews) {
if (mAdapter != null) {
mAdapter.unregisterAdapterDataObserver(mObserver);
mAdapter.onDetachedFromRecyclerView(this);
if (!compatibleWithPrevious || removeAndRecycleViews) {//对之前的View、动画、装饰等视图进行回收
//一般情况会进到这里
if (mItemAnimator != null) {
mItemAnimator.endAnimations();
if (mLayout != null) {
mLayout.removeAndRecycleAllViews(mRecycler);
mLayout.removeAndRecycleScrapInt(mRecycler);
mRecycler.clear();
mAdapterHelper.reset();
final Adapter oldAdapter = mA
mAdapter = //赋予新值
if (adapter != null) {
adapter.registerAdapterDataObserver(mObserver);
adapter.onAttachedToRecyclerView(this); //在方法内部针对GridLayoutManager布局进行的设置,使得可以显示Header和Footer视图
if (mLayout != null) {
mLayout.onAdapterChanged(oldAdapter, mAdapter);
mRecycler.onAdapterChanged(oldAdapter, mAdapter, compatibleWithPrevious);
mState.mStructureChanged =
该方法的主要动作是,移除LayoutManager中的视图、清空Recycler mRecycler中的数据、更新Adapter mAdapter域、注册数据观察者、Adapter和RecyclerView绑定;
小结:addItemDecoration、setItemAnimator、setLayoutManager和setAdapter几个方法相对简单,大体都是更新RecyclerView中的相关域,方法的最后会申请requestLayout进行绘制。
Partt2——事件分发
分析完上面几个常用的方法我们分析一下滑动过程中RecyclerView是如何动态刷新视图的。
onTouchEvent()@RecyclerView.class
public boolean onTouchEvent(MotionEvent e) {
if (dispatchOnItemTouch(e)) { //note1
cancelTouch();
if (mLayout == null) { }
switch (action) {
case MotionEvent.ACTION_DOWN: { //记录当前按下的坐标值
mInitialTouchX = mLastTouchX = (int) (e.getX() + 0.5f);
mInitialTouchY = mLastTouchY = (int) (e.getY() + 0.5f);
case MotionEvent.ACTION_MOVE: {
final int index = MotionEventCompat.findPointerIndex(e, mScrollPointerId);
if (index & 0) { }
final int x = (int) (MotionEventCompat.getX(e, index) + 0.5f);
final int y = (int) (MotionEventCompat.getY(e, index) + 0.5f);
int dx = mLastTouchX -
int dy = mLastTouchY -
if (dispatchNestedPreScroll(dx, dy, mScrollConsumed, mScrollOffset)) {
dx -= mScrollConsumed[0];
dy -= mScrollConsumed[1];
vtev.offsetLocation(mScrollOffset[0], mScrollOffset[1]);
mNestedOffsets[0] += mScrollOffset[0];
mNestedOffsets[1] += mScrollOffset[1];
if (mScrollState != SCROLL_STATE_DRAGGING) { //不是在拖动页面
boolean startScroll =
if (canScrollHorizontally && Math.abs(dx) & mTouchSlop) {
if (dx & 0) {
dx -= mTouchS } else { dx += mTouchS}
startScroll =
if (canScrollVertically && Math.abs(dy) & mTouchSlop) {
if (dy & 0) {
dy -= mTouchS } else {
dy += mTouchS }
startScroll =
if (startScroll) {
setScrollState(SCROLL_STATE_DRAGGING);//note2
if (mScrollState == SCROLL_STATE_DRAGGING) {
mLastTouchX = x - mScrollOffset[0];
mLastTouchY = y - mScrollOffset[1];
if (scrollByInternal( canScrollHorizontally ? dx : 0, canScrollVertically ? dy : 0,
vtev)) //note3
getParent().requestDisallowInterceptTouchEvent(true); }
vtev.recycle();
1、分派当前事件给子View处理,如果没有任何子View处理则进行后续操作
2、该方法内部如下
小结:在事件分发中,首先将事件分派给子View去处理,如果子View没有消耗当前事件,则事件才会交给RecyclerView执行。RecyclerView可能对事件再包装交给自己的监听器去处理也可能触发刷新视图的操作,具体通过调用LayoutManager的scrollXXBy方法。
Part3——绘制流程
对于RecyclerView的绘制流程,因为它继承自ViewGroup,因此我们首先回顾一下ViewGroup的绘制流程:
ViewGroup没有重写View的onMeasure方法,但提供了一个measureChildren方法用于调用children的measure方法,但是很多子类都不用该方法,而是自己重写View的onMeasure方法。ViewGroup重写了View的onLayout方法,但是声明为抽象方法交给子类实现。ViewGroup没有重写View的draw和onDraw方法,但是View的draw方法会调用dispatchDraw(canvas)方法,ViewGroup实现了dispatchDraw(canvas)方法,对于dispatchDraw(canvas)方法ViewGroup子类一般都不会去重写。
所以ViewGroup要求子类必须实现onLayout方法,对ViewGroup下面的View显示位置方式进行控制。下面按照onMeasure、onLayout、draw和onDraw的顺序来分析RecyclerView的绘制流程。
onMeasure()@RecyclerView.class
protected void onMeasure(int widthSpec, int heightSpec) {
if (mLayout == null) {
defaultOnMeasure(widthSpec, heightSpec);//note0
if (mLayout.mAutoMeasure) {
mLayout.onMeasure(mRecycler, mState, widthSpec, heightSpec);//note1
mLayout.setMeasureSpecs(widthSpec, heightSpec);
mLayout.setMeasuredDimensionFromChildren(widthSpec, heightSpec);//note2
if (mHasFixedSize) {
mLayout.onMeasure(mRecycler, mState, widthSpec, heightSpec);
mLayout.onMeasure(mRecycler, mState, widthSpec, heightSpec);
0、方法实现如下
2、mLayout.setMeasuredDimensionFromChildren顾名思义就是调用子View的onMeasure方法。
onMeasure暂时没有我们太关心的东西,接着往下看。
onLayout()@RecyclerView.class
protected void onLayout(boolean changed, int l, int t, int r, int b) {
dispatchLayout();
void dispatchLayout() {
if (mAdapter == null) {
if (mLayout == null) { }
mState.mIsMeasuring =
if (mState.mLayoutStep == State.STEP_START) {
dispatchLayoutStep1();
mLayout.setExactMeasureSpecsFrom(this);
dispatchLayoutStep2();
} else if (mAdapterHelper.hasUpdates() || mLayout.getWidth() != getWidth() ||
mLayout.getHeight() != getHeight()) {
mLayout.setExactMeasureSpecsFrom(this);
dispatchLayoutStep2();
mLayout.setExactMeasureSpecsFrom(this);
dispatchLayoutStep3();
该方法主要是对LayoutManager的相关方法的调用,后面LayoutManager.class部分会再讲。
draw()@RecyclerView.class
public void draw(Canvas c) {
super.draw(c);
//内部会调用执行完onDraw方法之后才返回
final int count = mItemDecorations.size();
for (int i = 0; i & i++) {
mItemDecorations.get(i).onDrawOver(c, this, mState); //会在temDecoration的onDraw之后调用
给itemView绘制完后在其基础上绘制一些装饰图案
onDraw()@RecyclerView.class
public void onDraw(Canvas c) {
super.onDraw(c);
final int count = mItemDecorations.size();
for (int i = 0; i & i++) {
mItemDecorations.get(i).onDraw(c, this, mState); //会在temDecoration的onDrawOver之前调用
在itemView绘制之前绘制一些装饰如背景、画布形状。
小结:本节分析的onMeasure和onLayout方法暂时没有找到令我们兴奋 的东西,但是在Draw和onDraw方法中我们找到了ItemDecoration的使用!在每次RecyclerView正式绘制之前都会先调用ItemDecorations集合中所有的ItemDecoration对象的onDraw方法,等ItemView绘制完毕,再调用ItemDecorations集合中所有的ItemDecoration对象的onDrawOver方法。
到此为止我们分析完了Part1、Part2、Part3三部分,中间遇到了如下的一些方法还没有解释清楚。
onDetachedFromRecyclerView、onAttachedToRecyclerView、registerAdapterDataObserver、unregisterAdapterDataObserver
LayoutManager
setRecyclerView、onAdapterChanged、dispatchDetachedFromWindow、dispatchAttachedToWindow、removeAndRecycleAllViews、removeAndRecycleScrapInt、scrollHorizontallyBy、scrollVerticallyBy
下面我们就按照这里的顺序依次查看这些方法底层的实现。
Adapter.calss
onAttachedToRecyclerView()@Adapter.class
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
当RecyclerView开始使用当前Adapter对象时会调用该方法
onDetachedFromRecyclerView()@Adapter.class
public void onDetachedFromRecyclerView(RecyclerView recyclerView) {
当RecyclerView停止使用当前Adapter对象时会调用该方法
registerAdapterDataObserver()@Adapter.class
public void registerAdapterDataObserver(AdapterDataObserver observer) {
& & &mObservable.registerObserver(observer);
注册一个新的观察者
unregisterAdapterDataObserver()@Adapter.class
public void unregisterAdapterDataObserver(AdapterDataObserver observer) {
& & mObservable.unregisterObserver(observer);
注销一个观察者
notifyItemInserted()@Adapter.class
public final void notifyItemInserted(int position) {
& & &mObservable.notifyItemRangeInserted(position, 1);
通过mObservable去通知所有的观察者处理该事件
小结:Adapter是RecyclerView的数据供应方,当Adapter和RecyclerView绑定的时候其实就是一个相互引用的过程。绑定过程中RecyclerView注册成为Adapter的观察者,一旦Adapter中的数据发生改变就通过调用Adapter的notifyXX方法告知RecyclerView去刷新视图。绑定过程中Adapter可以通过onAttachedToRecyclerView()方法对RecyclerView进行相应的处理。
注意:当有数据更新的时候,需要通知对应的Adapter;而对于RecyclerView而言,不能够仅仅通过调用notifyDataSetChanged()就完事儿了的,因为RecyclerView还有更多精细的动作,需要处理,而不像listView那么简单;因此推荐一旦有事件需要处理则调用方法notifyItemXX();&
如果我们在RecyclerView第一栏中添加了一行数据,而且希望RecyclerView显示这一行数据:adapter.notifyItemInserted(0); & recyclerView.scrollToPosition(0);&如果我们在RecyclerView最后栏中添加了一行数据,而且希望RecyclerView显示这一行数据:adapter.notifyItemInserted(contacts.size() - 1); & recyclerView.scrollToPosition(mAdapter.getItemCount() - 1);
contacts是我们的data数据集;
下面我们分析LayoutManager对象,LayoutManager的子类比较多,我们不妨以简单的LinearLayoutManager方法为例进行说明。
LinearLayoutManager.class
& & LayoutManager 主要作用是,测量和摆放RecyclerView中itemView,以及当itemView对用户不可见时循环复用处理。 通过RecycleView.set.LayoutManager()方法将自定义LayoutManager和RecycleView进行绑定。通过设置Layout Manager的属性,可以实现水平滚动、垂直滚动、方块表格等列表形式。
ChildHelper mChildH //负责管理LayoutManager使用的ItemView
RecyclerView mRecyclerV //与之绑定的RecyclerView
setRecyclerView()@LayoutManager.class
void setRecyclerView(RecyclerView recyclerView) {
if (recyclerView == null) {
mRecyclerView =
mChildHelper =
mWidthSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.EXACTLY);
mHeightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.EXACTLY);
mRecyclerView = recyclerV
mChildHelper = recyclerView.mChildH
mWidthSpec = MeasureSpec
.makeMeasureSpec(recyclerView.getWidth(), MeasureSpec.EXACTLY);
mHeightSpec = MeasureSpec
.makeMeasureSpec(recyclerView.getHeight(), MeasureSpec.EXACTLY);
对LayoutManager中的域完成初始化值的设置,如mChildHelper和mRecyclerView
onAdapterChanged()@LayoutManager.class
public void onAdapterChanged(Adapter oldAdapter, Adapter newAdapter) {
空方法没有子类实现它
dispatchDetachedFromWindow()@LayoutManager.class
void dispatchDetachedFromWindow(RecyclerView view, Recycler recycler) {
mIsAttachedToWindow =
onDetachedFromWindow(view, recycler);
onDetachedFromWindow()@LinearLayoutManager.class
public void onDetachedFromWindow(RecyclerView view, RecyclerView.Recycler recycler) {
if (mRecycleChildrenOnDetach) {
removeAndRecycleAllViews(recycler);
recycler.clear();
removeAndRecycleAllViews()@LayoutManager.class
public void removeAndRecycleAllViews(Recycler recycler) {
for (int i = getChildCount() - 1; i &= 0; i--) { //内部调用mChildHelper.getChildCount()
final View view = getChildAt(i); //内部调用mChildHelper.getChildAt(index)
if (!getChildViewHolderInt(view).shouldIgnore()) { //note1
removeAndRecycleViewAt(i, recycler);
1、getChildViewHolderInt(view):通过当前view的LayoutParams值获取ViewHolder、这里的LayoutParams是RecyclerView的内部类,由当前View对应的ViewHolder
removeAndRecycleViewAt()@LayoutManager.class
public void removeAndRecycleViewAt(int index, Recycler recycler) {
final View view = getChildAt(index); //内部调用mChildHelper.getChildAt(index)
removeViewAt(index); //内部调用mChildHelper.removeViewAt(index);
recycler.recycleView(view);
小结:dispatchDetachedFromWindow()方法中主要是调用了removeViewAt(index)、recycler.recycleView(view)和recycler.clear()方法。removeViewAt(index)将RecyclerView不再使用的View移除;recycler.recycleView(view)用于回收该ViewHolder。LayoutManager使用中的View都是交给ChildHelper完成的,Recycler负责回收ViewHolder。
dispatchAttachedToWindow()@LayoutManager.class
void dispatchAttachedToWindow(RecyclerView view) {
mIsAttachedToWindow =
onAttachedToWindow(view);//note1
1、该方法留给子类实现,但是子类基本都没有重写该方法
removeAndRecycleAllViews()@LayoutManager.class
该部分已经在dispatchDetachedFromWindow()@LayoutManager.class中介绍过
removeAndRecycleScrapInt()@LayoutManager.class
void removeAndRecycleScrapInt(Recycler recycler) {
final int scrapCount = recycler.getScrapCount();
for (int i = scrapCount - 1; i &= 0; i--) {
final View scrap = recycler.getScrapViewAt(i);
final ViewHolder vh = getChildViewHolderInt(scrap); //note1
if (vh.shouldIgnore()) { }
vh.setIsRecyclable(false); //避免因关闭动画而导致的重复回收
if (vh.isTmpDetached()) {
mRecyclerView.removeDetachedView(scrap, false);
if (mRecyclerView.mItemAnimator != null) {
mRecyclerView.mItemAnimator.endAnimation(vh);
} //结束动画
vh.setIsRecyclable(true);
recycler.quickRecycleScrapView(scrap);
recycler.clearScrap();
if (scrapCount & 0) {
mRecyclerView.invalidate();
1、getChildViewHolderInt(view):通过当前view的LayoutParams值获取ViewHolder、这里的LayoutParams是RecyclerView的内部类,由当前View对应的ViewHolder
scrollHorizontallyBy()@LayoutManager.calss
public int scrollHorizontallyBy(int dx, Recycler recycler, State state) {
scrollHorizontallyBy()@LinearLayoutManager.calss
public int scrollHorizontallyBy(int dx, RecyclerView.Recycler recycler,
RecyclerView.State state) {
if (mOrientation == VERTICAL) {
return 0; }
return scrollBy(dx, recycler, state);
scrollBy()@LinearLayoutManager.calss
int scrollBy(int dy, RecyclerView.Recycler recycler, RecyclerView.State state) {
if (getChildCount() == 0 || dy == 0) { //内部调用mChildHelper.getChildCount()方法
mLayoutState.mRecycle =
ensureLayoutState(); //mLayoutState和mOrientationHelper初始化设置
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); //绘制肯定在fill方法内部
if (consumed & 0) {
final int scrolled = absDy & consumed ? layoutDirection * consumed :
mOrientationHelper.offsetChildren(-scrolled);
mLayoutState.mLastScrollDelta =
fill()@LinearLayoutManager.calss
int fill(RecyclerView.Recycler recycler, LayoutState layoutState, RecyclerView.State state, boolean stopOnFocusable) {
final int start = layoutState.mA
int remainingSpace = layoutState.mAvailable + layoutState.mE
LayoutChunkResult layoutChunkResult = new LayoutChunkResult();
while ((layoutState.mInfinite || remainingSpace & 0) && layoutState.hasMore(state)) {
layoutChunkResult.resetInternal(); //layoutChunkResult域初始化
layoutChunk(recycler, state, layoutState, layoutChunkResult); //note1 具体内容见后面
if (layoutChunkResult.mFinished) { }
} //end of While
return start - layoutState.mA
layoutChunk()@LinearLayoutManager.calss
void layoutChunk(RecyclerView.Recycler recycler, RecyclerView.State state,
LayoutState layoutState, LayoutChunkResult result) {
View view = layoutState.next(recycler); //note1
LayoutParams params = (LayoutParams) view.getLayoutParams();
if (layoutState.mScrapList == null) {
if (mShouldReverseLayout == (layoutState.mLayoutDirection
== LayoutState.LAYOUT_START)) {
addView(view); //note2
addView(view, 0);
if (mShouldReverseLayout == (layoutState.mLayoutDirection
== LayoutState.LAYOUT_START)) {
addDisappearingView(view);
addDisappearingView(view, 0);
measureChildWithMargins(view, 0, 0); //会调用childView.measure方法
layoutDecorated(view, left + params.leftMargin, top + params.topMargin,
right - params.rightMargin, bottom - params.bottomMargin); //会调用childView.layout方法
if (params.isItemRemoved() || params.isItemChanged()) {
result.mIgnoreConsumed =
result.mFocusable = view.isFocusable();
next()@ LayoutState.class@LinearLayoutManager.class
List&RecyclerView.ViewHolder& mScrapList =
View next(RecyclerView.Recycler recycler) {
if (mScrapList != null) {
return nextViewFromScrapList(); //note1
final View view = recycler.getViewForPosition(mCurrentPosition);
mCurrentPosition += mItemD
利用recycler的getViewForPosition获取一个View,该部分我们放到后面讲
addView()@LayoutManager.calss
将View添加到RecyclerView中
scrollHorizontallyBy()@LayoutManager.calss
public int scrollVerticallyBy(int dy, Recycler recycler, State state) {
scrollVerticallyBy()@LinearLayoutManager.calss
public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler,
RecyclerView.State state) {
if (mOrientation == HORIZONTAL) {
return scrollBy(dy, recycler, state); //该方法在前面scrollHorizontallyBy()@LayoutManager.calss已经介绍过了
LayoutManager负责测量和摆放RecyclerView中itemView,利用ChildHelper mChildHelper管理LayoutManager使用的ItemView,利用Recycler获取回收View。简单讲就是从Recycler中取数据然后进行显示。
上面分析完了Adapter.class和LayoutManager.class,接着我们分析RecyclerView中非常重要的资源回收部分,这部分的操作实体是Recycler.class,下面我们需要重点分析的方法:
recycler.clearScrap()recycler.getScrapViewAt(i)recycler.clear()recycler.recycleView(view)recycler.getViewForPosition(mCurrentPosition);recycler.quickRecycleScrapView(scrap)
Recycler.class——视图资源回收
View getScrapViewAt(int index) {
return mAttachedScrap.get(index).itemV
private ArrayList&ViewHolder& mChangedScrapprivate ArrayList&ViewHolder& mAttachedScrapprivate ArrayList&ViewHolder& mCachedViews &//ViewHolder缓存列表,一级缓存private ViewCacheExtension mViewCacheExtension //由开发者控制的可以作为View缓存的帮助类,默认是获取nullprivate RecycledViewPool mRecyclerPool 提供复用ViewHolder池。
SparseArray&ArrayList&ViewHolder&& mS//每一个Type对应一个List,Type为int型,也就是说我们映射的键是int型而非一个对象,这点跟SparseArray这个集合有关!SparseIntArray mMaxScrap = new SparseIntArray();//每个Type对应的最大ViewHolder数量!RecyclerViewPool用于多个RecyclerView之间共享View;RecyclerView默认会创建一个RecyclerViewPool实例。也可通过setRecycledViewPool(RecycledViewPool) 方法,让RecycleView使用自定义RecyclerViewPool;
RecyclerView的视图回收流程是:
调用Recycler.getViewForPosition(int)方法获取View时,Recycler先检查mChangedScrap和mAttachedScrap ,没命中进行如下操作调用ViewCacheExtension.getViewForPositionAndType(Recycler, int, int)获取View,没命中进行如下操作检查RecyclerViewPool,如果还是没有命中则内部会调用Adapter的onCreateViewHolder等方法创建一个新的ViewHolder。
ListView的setAdapter方法内部会调用mRecycler.setViewTypeCount(mAdapter.getViewTypeCount())方法,方法会给RecycleBin创建mAdapter.getViewTypeCount()个ArrayList集合,每个集合对应一个View类型。android.widget.BaseAdapter的getViewTypeCount()方法默认返回1。表明在将Adapter和ListView绑定的那一刻起,RecycleBin所能缓存的View类型数是一定的。setViewTypeCount()内容如下:
private ArrayList&View&[] mScrapV
public void setViewTypeCount(int viewTypeCount) {
& & & & & & if (viewTypeCount & 1) { thow....}&
& & & & & & ArrayList&View&[] scrapViews = new ArrayList[viewTypeCount];
& & & & & & for (int i = 0; i & viewTypeC i++) {
& & & & & & & & scrapViews[i] = new ArrayList&View&();
& & & & & & }
& & & & & & mViewTypeCount = viewTypeC
& & & & & & mCurrentScrap = scrapViews[0];
& & & & & & mScrapViews = scrapV
RecyclerView的RecycledViewPool采用SparseArray+ArrayList的形式:
private SparseArray&ArrayList&ViewHolder&& mScrap = new SparseArray&ArrayList&ViewHolder&&();final ArrayList&ViewHolder& scrapHeap = mScrap.get(viewType);注意:SparseArray是一个很神奇的数组,可以不按照位置存储数据,比如当前集合大小为10我们可以在15的位置插上一个数据,通过get(15)获取到对应的内容!以后有时间我们好好探究其如何实现!!
我的热门文章
即使是一小步也想与你分享}

我要回帖

更多关于 recyclerview点击item 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信