下面是分析ListView初始化的原始碼流程分析,主要是ListVIew.onLayout過程與普通檢視的layout過程完全不同,避免流程交代不清楚,以下是一個流程的思維導圖。
思維導圖是順序是從左向右,從上向下。
一、 先看建構函式,上圖中1.1就不分析了,主要是讀取一些ListView引數,直接來看1.2 ViewGroup建構函式原始碼
-
private void initViewGroup() {
-
......
-
-
mChildren = new View[ARRAY_INITIAL_CAPACITY];
-
-
mChildrenCount = 0;
-
......
-
}
檢視的建立過程的都會執行的三個步驟: onMeasure, onLayout, onDraw
二、接著2 即 ListView.onMeasure方法,只是獲取當前ListView的寬高
-
@Override
-
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-
-
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
-
-
-
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
-
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
-
-
......
-
-
setMeasuredDimension(widthSize , heightSize);
-
mWidthMeasureSpec = widthMeasureSpec;
-
}
三、步驟3是重點,AbsListView.onLayout的流程與普通View的不同
-
@Override
-
protected void onLayout(boolean changed, int l, int t, int r, int b) {
-
super.onLayout(changed, l, t, r, b);
-
mInLayout = true;
-
-
if (changed) {
-
int childCount = getChildCount();
-
for (int i = 0; i < childCount; i++) {
-
-
getChildAt(i).forceLayout();
-
}
-
mRecycler.markChildrenDirty();
-
}
-
-
if (mFastScroller != null && mItemCount != mOldItemCount) {
-
mFastScroller.onItemCountChanged(mOldItemCount, mItemCount);
-
}
-
-
-
layoutChildren();
-
mInLayout = false;
-
-
mOverscrollMax = (b - t) / OVERSCROLL_LIMIT_DIVISOR;
-
}
四、步驟4.1 具體分析ListVIew.layoutChildren
-
@Override
-
protected void layoutChildren() {
-
-
final boolean blockLayoutRequests = mBlockLayoutRequests;
-
if (!blockLayoutRequests) {
-
-
mBlockLayoutRequests = true;
-
} else {
-
return;
-
}
-
-
try {
-
super.layoutChildren();
-
-
invalidate();
-
-
......
-
-
int childCount = getChildCount();
-
-
......
-
-
boolean dataChanged = mDataChanged;
-
if (dataChanged) {
-
handleDataChanged();
-
}
-
-
......
-
-
-
-
final int firstPosition = mFirstPosition;
-
-
-
final RecycleBin recycleBin = mRecycler;
-
-
-
View focusLayoutRestoreDirectChild = null;
-
-
-
-
if (dataChanged) {
-
for (int i = 0; i < childCount; i++) {
-
recycleBin.addScrapView(getChildAt(i), firstPosition+i);
-
}
-
} else {
-
-
recycleBin.fillActiveViews(childCount, firstPosition);
-
}
-
-
......
-
-
-
detachAllViewsFromParent();
-
recycleBin.removeSkippedScrap();
-
-
switch (mLayoutMode) {
-
-
......
-
-
default:
-
if (childCount == 0) {
-
if (!mStackFromBottom) {
-
final int position = lookForSelectablePosition(0, true);
-
setSelectedPositionInt(position);
-
-
sel = fillFromTop(childrenTop);
-
} else {
-
final int position = lookForSelectablePosition(mItemCount - 1, false);
-
setSelectedPositionInt(position);
-
sel = fillUp(mItemCount - 1, childrenBottom);
-
}
-
} else {
-
if (mSelectedPosition >= 0 && mSelectedPosition < mItemCount) {
-
sel = fillSpecific(mSelectedPosition,
-
oldSel == null ? childrenTop : oldSel.getTop());
-
} else if (mFirstPosition < mItemCount) {
-
sel = fillSpecific(mFirstPosition,
-
oldFirst == null ? childrenTop : oldFirst.getTop());
-
} else {
-
sel = fillSpecific(0, childrenTop);
-
}
-
}
-
break;
-
}
-
-
-
recycleBin.scrapActiveViews();
-
-
......
-
-
invokeOnItemScrollListener();
-
} finally {
-
if (!blockLayoutRequests) {
-
mBlockLayoutRequests = false;
-
}
-
}
五、 分析步驟4.2 ListView.fillFromTop原始碼
-
-
private View fillFromTop(int nextTop) {
-
mFirstPosition = Math.min(mFirstPosition, mSelectedPosition);
-
mFirstPosition = Math.min(mFirstPosition, mItemCount - 1);
-
if (mFirstPosition < 0) {
-
mFirstPosition = 0;
-
}
-
-
return fillDown(mFirstPosition, nextTop);
-
}
六、檢視步驟4.3 ListView.fillDown原始碼
-
-
private View fillDown(int pos, int nextTop) {
-
View selectedView = null;
-
-
-
int end = (mBottom - mTop);
-
if ((mGroupFlags & CLIP_TO_PADDING_MASK) == CLIP_TO_PADDING_MASK) {
-
end -= mListPadding.bottom;
-
}
-
-
-
-
while (nextTop < end && pos < mItemCount) {
-
-
boolean selected = pos == mSelectedPosition;
-
-
View child = makeAndAddView(pos, nextTop, true, mListPadding.left, selected);
-
-
nextTop = child.getBottom() + mDividerHeight;
-
if (selected) {
-
selectedView = child;
-
}
-
pos++;
-
}
-
-
setVisibleRangeHint(mFirstPosition, mFirstPosition + getChildCount() - 1);
-
return selectedView;
-
}
七、檢視步驟4.4 ListView.makeAndAddView原始碼
-
-
-
private View makeAndAddView(int position, int y, boolean flow, int childrenLeft,
-
boolean selected) {
-
View child;
-
-
ListView的資料發生變化,肯定Item View之前已經建立好了,無需重新建立
-
if (!mDataChanged) {
-
-
child = mRecycler.getActiveView(position);
-
if (child != null) {
-
-
setupChild(child, position, y, flow, childrenLeft, selected, true);
-
-
return child;
-
}
-
}
-
-
-
child = obtainView(position, mIsScrap);
-
-
-
setupChild(child, position, y, flow, childrenLeft, selected, mIsScrap[0]);
-
-
return child;
-
}
八 檢視步驟4.5 ListView.setupChild原始碼
-
private void setupChild(View child, int position, int y, boolean flowDown, int childrenLeft,
-
boolean selected, boolean recycled) {
-
-
final boolean isSelected = selected && shouldShowSelector();
-
final boolean updateChildSelected = isSelected != child.isSelected();
-
-
final int mode = mTouchMode;
-
-
-
final boolean isPressed = mode > TOUCH_MODE_DOWN && mode < TOUCH_MODE_SCROLL &&
-
mMotionPosition == position;
-
final boolean updateChildPressed = isPressed != child.isPressed();
-
-
-
final boolean needToMeasure = !recycled || updateChildSelected || child.isLayoutRequested();
-
-
-
-
AbsListView.LayoutParams p = (AbsListView.LayoutParams) child.getLayoutParams();
-
if (p == null) {
-
p = (AbsListView.LayoutParams) generateDefaultLayoutParams();
-
}
-
p.viewType = mAdapter.getItemViewType(position);
-
-
if ((recycled && !p.forceAdd) || (p.recycledHeaderFooter &&
-
p.viewType == AdapterView.ITEM_VIEW_TYPE_HEADER_OR_FOOTER)) {
-
attachViewToParent(child, flowDown ? -1 : 0, p);
-
} else {
-
p.forceAdd = false;
-
if (p.viewType == AdapterView.ITEM_VIEW_TYPE_HEADER_OR_FOOTER) {
-
p.recycledHeaderFooter = true;
-
}
-
-
addViewInLayout(child, flowDown ? -1 : 0, p, true);
-
}
-
-
-
if (updateChildSelected) {
-
child.setSelected(isSelected);
-
}
-
-
-
if (updateChildPressed) {
-
child.setPressed(isPressed);
-
}
-
-
if (mChoiceMode != CHOICE_MODE_NONE && mCheckStates != null) {
-
if (child instanceof Checkable) {
-
((Checkable) child).setChecked(mCheckStates.get(position));
-
} else if (getContext().getApplicationInfo().targetSdkVersion
-
>= android.os.Build.VERSION_CODES.HONEYCOMB) {
-
child.setActivated(mCheckStates.get(position));
-
}
-
}
-
-
if (needToMeasure) {
-
int childWidthSpec = ViewGroup.getChildMeasureSpec(mWidthMeasureSpec,
-
mListPadding.left + mListPadding.right, p.width);
-
int lpHeight = p.height;
-
int childHeightSpec;
-
if (lpHeight > 0) {
-
childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight, MeasureSpec.EXACTLY);
-
} else {
-
childHeightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
-
}
-
-
child.measure(childWidthSpec, childHeightSpec);
-
} else {
-
cleanupLayoutState(child);
-
}
-
-
final int w = child.getMeasuredWidth();
-
final int h = child.getMeasuredHeight();
-
final int childTop = flowDown ? y : y - h;
-
-
if (needToMeasure) {
-
final int childRight = childrenLeft + w;
-
final int childBottom = childTop + h;
-
-
child.layout(childrenLeft, childTop, childRight, childBottom);
-
} else {
-
child.offsetLeftAndRight(childrenLeft - child.getLeft());
-
child.offsetTopAndBottom(childTop - child.getTop());
-
}
-
-
if (mCachingStarted && !child.isDrawingCacheEnabled()) {
-
child.setDrawingCacheEnabled(true);
-
}
-
-
if (recycled && (((AbsListView.LayoutParams)child.getLayoutParams()).scrappedFromPosition)
-
!= position) {
-
child.jumpDrawablesToCurrentState();
-
}
-
}
轉載請註明原文地址:http://blog.csdn.net/love_world_/article/details/8547077