一、RecycleBin
ListView的回收机制是通过RecycleBin来完成的,这个类在AbsListView(AbsListView的子类有GridView和ListView)中,下面对这个类的关键成员变量和方法进行解释:
1、变量mActiveViews:是一个view数组,用来存储屏幕上显示的View。
2、变量mScrapViews:是一个ArrayList的数组,用来存储滑出屏幕后的View。
3、方法fillActiveViews(int childCount, int firstActivePosition) :存储ListView中可见的Item的view,在notifyDataSetChanged方法执行后,假如界面中item的数据没有改变则把View添加到mActiveViews集合中。在ListView中的layoutChildren方法里面调用。
4、方法getActiveView:获取ListView中可见的item中的view,在notifyDataSetChanaged方法执行后,如果数据没有改变则获取这个view。在makeAndAddView方法中调用。
5、方法addScrapView:添加view到回收的mScrapViews集合中,当item滑出屏幕后执行。在layoutChildren方法中调用。</p><p>6、方法getSrapView:从回收中的集合获取一个view对象,当屏幕有新的item展示的时候会调用。在AbsListView中的obtainView中调用。
6、方法getSrapView:从回收中的集合获取一个view对象,当屏幕有新的item展示的时候会调用。在AbsListView中的obtainView中调用。
7、方法retrieveFromScrap:在getScrapView中调用,从回收的view集合里面查找view。这里有三种情况:
(1)假如ListView刚刚展示五个view,当我们往下滑动的时候,第六个view展示,这个时候mScrapViews中没有存储任何的View对象,所以返回null。
(2)当用户继续向下滑动第一个view不可见,这个时候会添加到mScrapViews集合里面去,如果上滑,第一个view又重新展示,这个时候会通过位置来拿到mCrapViews中的view。
(3)接着(2)中向下滑动第七个view展示,那么就会获取mScrapViews集合中最后一个View。
二、在ListView中的调用分析
接下来通过mLayoutMode布局类型来获取item里面的view,其中布局类型可以从上往下绘制,从中间绘制,从指定的位置绘制等等。都会调用fill开头的方法,从顶部绘制fillFromTop,指定位置绘制fillFromSelection,中间布局fillFromMiddle等。其中都会调用makeAndAddView这个方法来获取view对象。下面看这个方法:
2、makeAndAddView
数据没有变的时候就从RecycleBin对象里面的mActiveViews集合获取view,否则从回收的集合mScrapViews里面获取,具体调用obtain方法。这里面其实做了一个优化,就是数据更新的时候假如数据没有变直接从集合里面取出view对象即可。
if (!mDataChanged) {
// Try to use an existing view for this position
child = mRecycler.getActiveView(position);
if (child != null) {
// Found it -- we're using an existing child
// This just needs to be positioned
setupChild(child, position, y, flow, childrenLeft, selected, true);
return child;
}
}
// Make a new view for this position, or convert an unused view if possible
child = obtainView(position, mIsScrap);3、obtainView方法
这个方法从回收的view中 获取view,假如没有则重新创建新的view。scrapView = mRecycler.getScrapView(position); 从RecycleBin获取回收的View
if (scrapView != null) {
child = mAdapter.getView(position, scrapView, this);
if (child.getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
child.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
}
if (child != scrapView) {
mRecycler.addScrapView(scrapView, position);
if (mCacheColorHint != 0) {
child.setDrawingCacheBackgroundColor(mCacheColorHint);
}
} else {
isScrap[0] = true;
// Clear any system-managed transient state so that we can
// recycle this view and bind it to different data.
if (child.isAccessibilityFocused()) {
child.clearAccessibilityFocus();
}
child.dispatchFinishTemporaryDetach();
}
} else {
child = mAdapter.getView(position, null, this);
if (child.getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
child.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
}
if (mCacheColorHint != 0) {
child.setDrawingCacheBackgroundColor(mCacheColorHint);
}
} 然后通过adapter的getView方法拿到回收的View或者重新创建一个view对象。
4、onTouchEvent方法
当我们的手指上下滑动的时候,RecycleBin是怎么工作的呢?这个时候会执行onTouch开头的方法,如ACTION_MOVE时候执行onTouchMove,追踪源码到trackMotionScroll方法,到fillGap方法。fillGap在ListView中实现的,然后调用fillDown或者fillUp方法。在fill开头的方法里面会调用makeAndAddView方法。
本文详细解析了ListView的回收机制,包括RecycleBin类的关键成员变量和方法,以及在ListView中的调用分析。

1万+

被折叠的 条评论
为什么被折叠?



