1. ListView的继承关系
ListView2.setViewTypeCount
在调用ListView的setAdapter方法时,会调用setViewTypeCount对缓存容器RecycleBin的数据结构进行初始化
frameworks\base\core\java\android\widget\ListView.java
(1)应用层调用setAdapter
public void setAdapter(ListAdapter adapter) {
if (mHeaderViewInfos.size() > 0|| mFooterViewInfos.size() > 0) {
mAdapter = wrapHeaderListAdapterInternal(mHeaderViewInfos, mFooterViewInfos, adapter);
} else {
mAdapter = adapter;
}
if (mAdapter != null) {
mRecycler.setViewTypeCount(mAdapter.getViewTypeCount());
}
}
(2)初始化RecycleBin的成员变量
public void setViewTypeCount(int viewTypeCount) {
if (viewTypeCount < 1) {
throw new IllegalArgumentException("Can't have a viewTypeCount < 1");
}
//noinspection unchecked
ArrayList<View>[] scrapViews = new ArrayList[viewTypeCount];
for (int i = 0; i < viewTypeCount; i++) {
scrapViews[i] = new ArrayList<View>(); //mScrapViews 的数组大小跟view type count一致
}
mViewTypeCount = viewTypeCount;
mCurrentScrap = scrapViews[0];
mScrapViews = scrapViews;
}
3. layoutChildren
protected void layoutChildren() {
if (dataChanged) { //如果数据改变
for (int i = 0; i < childCount; i++) {
recycleBin.addScrapView(getChildAt(i), firstPosition+i); //所有的view放入mScrapViews
}
} else { //没有改变,放入mActiveViews
recycleBin.fillActiveViews(childCount, firstPosition);
}
detachAllViewsFromParent(); //清除所有子view
fillFromTop(childrenTop);
recycleBin.scrapActiveViews(); //存在于mActiveViews的view移动至mScrapViews
}
Adapter getView的调用堆栈
IconListAdapter[72]--> getView
| <-- ( android.widget.AbsListView[2490]--> obtainView )
| <-- ( android.widget.ListView[2027]--> makeAndAddView )
| <-- ( android.widget.ListView[750]--> fillDown )
| <-- ( android.widget.ListView[815]--> fillFromTop )
| <-- ( android.widget.ListView[1801]--> layoutChildren )
| <-- ( android.widget.AbsListView[2278]--> onLayout )
4.fillFromTop
private View fillFromTop(int nextTop) {
return fillDown(mFirstPosition, nextTop);
}
5.fillDown
private View fillDown(int pos, int nextTop) {
while (nextTop < end && pos < mItemCount) {
View child = makeAndAddView(pos, nextTop, true, mListPadding.left, selected);
}
}
6.makeAndAddView
private View makeAndAddView(int position, int y, boolean flow, int childrenLeft,
boolean selected) {
if (!mDataChanged) {//数据未改变,从mActiveViews获得
final View activeView = mRecycler.getActiveView(position);
if (activeView != null) {
setupChild(activeView, position, y, flow, childrenLeft, selected, true);
return activeView;
}
}
//数据改变,或者没有获取到,调用obtainView进行获取
final View child = obtainView(position, mIsScrap);
setupChild(child, position, y, flow, childrenLeft, selected, mIsScrap[0]);
return child;
}
7.obtainView
View obtainView(int position, boolean[] outMetadata) {
//1.从mTransientStateViews获取
final View transientView = mRecycler.getTransientStateView(position);
if (transientView != null) {
return transientView;
}
//2.从mScrapViews处获取
final View scrapView = mRecycler.getScrapView(position);
//这里调用了mAdapter的getView,如果scrapView不为空,就不需要执行inflate方法来生成新view
final View child = mAdapter.getView(position, scrapView, this);
returrn child;
}
8.ListView滑动
将屏幕之外的view加至mScrapViews
boolean trackMotionScroll(int deltaY, int incrementalDeltaY) {
if (down) {
for (int i = 0; i < childCount; i++) {
final View child = getChildAt(i);
if (child.getBottom() >= top) {//view在可见范围
break;
} else {
count++;
int position = firstPosition + i;
if (position >= headerViewsCount && position < footerViewsStart) {
// The view will be rebound to new data, clear any
// system-managed transient state.
child.clearAccessibilityFocus();
mRecycler.addScrapView(child, position); //滑出范围之外,添加到mScrapViews
}
}
}
} else {
int bottom = getHeight() - incrementalDeltaY;
if ((mGroupFlags & CLIP_TO_PADDING_MASK) == CLIP_TO_PADDING_MASK) {
bottom -= listPadding.bottom;
}
for (int i = childCount - 1; i >= 0; i--) {
final View child = getChildAt(i);
if (child.getTop() <= bottom) {
break;
} else {
start = i;
count++;
int position = firstPosition + i;
if (position >= headerViewsCount && position < footerViewsStart) {
// The view will be rebound to new data, clear any
// system-managed transient state.
child.clearAccessibilityFocus();
mRecycler.addScrapView(child, position);//滑出范围之外,添加到mScrapViews
}
}
}
}
}
8.retrieveFromScrap
- id相同
- position相同
- 从尾部获取
private View retrieveFromScrap(ArrayList<View> scrapViews, int position) {
final int size = scrapViews.size();
if (size > 0) {
// See if we still have a view for this position or ID.
for (int i = 0; i < size; i++) {
final View view = scrapViews.get(i);
final AbsListView.LayoutParams params = (AbsListView.LayoutParams) view.getLayoutParams();
if (mAdapterHasStableIds) {
final long id = mAdapter.getItemId(position); //id相同
if (id == params.itemId) {
return scrapViews.remove(i);
}
} else if (params.scrappedFromPosition == position) { //position相同
final View scrap = scrapViews.remove(i);
clearAccessibilityFromScrap(scrap);
return scrap;
}
}
final View scrap = scrapViews.remove(size - 1); //从尾部获取
clearAccessibilityFromScrap(scrap);
return scrap;
} else {
return null;
}
}
9.clear
页面退出时,会执行clear方法,清除缓存的view
void clear() {
if (mViewTypeCount == 1) {
final ArrayList<View> scrap = mCurrentScrap;
clearScrap(scrap);
} else {
final int typeCount = mViewTypeCount;
for (int i = 0; i < typeCount; i++) {
final ArrayList<View> scrap = mScrapViews[i];
clearScrap(scrap);
}
}
clearTransientStateViews();
}
clear的调用堆栈
ListView--> onDetachedFromWindow
| <-- ( android.view.View[15673]--> dispatchDetachedFromWindow )
| <-- ( android.view.ViewGroup[3187]--> dispatchDetachedFromWindow )
| <-- ( android.view.ViewGroup[3179]--> dispatchDetachedFromWindow )
| <-- ( android.view.ViewGroup[3179]--> dispatchDetachedFromWindow )
| <-- ( android.view.ViewGroup[3179]--> dispatchDetachedFromWindow )
| <-- ( android.view.ViewGroup[3179]--> dispatchDetachedFromWindow )
| <-- ( android.view.ViewGroup[3179]--> dispatchDetachedFromWindow )
| <-- ( android.view.ViewGroup[3179]--> dispatchDetachedFromWindow )
| <-- ( android.view.ViewRootImpl[3296]--> dispatchDetachedFromWindow )
| <-- ( android.view.ViewRootImpl[6062]--> doDie )
| <-- ( android.view.ViewRootImpl[6039]--> die )
| <-- ( android.view.WindowManagerGlobal[457]--> removeViewLocked )
| <-- ( android.view.WindowManagerGlobal[395]--> removeView )
| <-- ( android.view.WindowManagerImpl[126]--> removeViewImmediate )
| <-- ( android.app.ActivityThread[4480]--> handleDestroyActivity )
网友评论