ListView 的源码实在太多, 重点分析ListView的几个机制
ListView的继承关系
可以看出,ListView和GridView的有极大的相似性,对ListView进行缓存,布局等操作都是在AbsListView中完成的.
RecycleBin机制
RecycleBin中的关键字段
RecycleBin将View分为两级,ActiveView和ScrapView,如果当前的view处于可见状态,将它放在ActiveView的数组中,如果ActiveView不可见了,开始将它降级为ScrapView,等待回收.
private RecyclerListener mRecyclerListener;
/**
* The position of the first view stored in mActiveViews.
*/
// 第一个ActiveView的下标,通过这个计算数组中的索引
private int mFirstActivePosition;
/**
* Views that were on screen at the start of layout. This array is populated at the start of
* layout, and at the end of layout all view in mActiveViews are moved to mScrapViews.
* Views in mActiveViews represent a contiguous range of Views, with position of the first
* view store in mFirstActivePosition.
*/
// ActiveView数组
private View[] mActiveViews = new View[0];
/**
* Unsorted views that can be used by the adapter as a convert view.
*/
// ScrapView数组,因为有可能多个ViewType,所以使用二维数组进行存储
private ArrayList<View>[] mScrapViews;
// ViewType的数量,通过这个创建ScrapHeap
private int mViewTypeCount;
private ArrayList<View> mCurrentScrap;
private ArrayList<View> mSkippedScrap;
private SparseArray<View> mTransientStateViews;
private LongSparseArray<View> mTransientStateViewsById;
RecycleBin中的关键方法
fillActiveViews()
RecycleBin当中使用mActiveViews
这个数组来存储View,调用这个方法后就会根据传入的参数来将ListView中的指定元素存储到mActiveViews数组当中。
/**
* Fill ActiveViews with all of the children of the AbsListView.
*
* @param childCount The minimum number of views mActiveViews should hold
* @param firstActivePosition The position of the first view that will be stored in
* mActiveViews
*/
void fillActiveViews(int childCount, int firstActivePosition) {
//针对数据,调整数组大小
if (mActiveViews.length < childCount) {
mActiveViews = new View[childCount];
}
// 记录ActiveView的首位置
mFirstActivePosition = firstActivePosition;
//noinspection MismatchedReadAndWriteOfArray
final View[] activeViews = mActiveViews;
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
// 调整LayoutParams
AbsListView.LayoutParams lp = (AbsListView.LayoutParams) child.getLayoutParams();
// Don't put header or footer views into the scrap heap
// 除Header,Footer之外其他View将添加到ActiveView数组中
if (lp != null && lp.viewType != ITEM_VIEW_TYPE_HEADER_OR_FOOTER) {
// Note: We do place AdapterView.ITEM_VIEW_TYPE_IGNORE in active views.
// However, we will NOT place them into scrap views.
activeViews[i] = child;
// Remember the position so that setupChild() doesn't reset state.
lp.scrappedFromPosition = firstActivePosition + i;
}
}
}
未完 doing….