Android ListView初始化简单分析

下面是分析ListView初始化的源码流程分析,主要是ListVIew.onLayout过程与普通视图的layout过程完全不同,避免流程交代不清楚,以下是一个流程的思维导图。

思维导图是顺序是从左向右,从上向下。

一、 先看构造函数,上图中1.1就不分析了,主要是读取一些ListView参数,,直接来看1.2 ViewGroup构造函数源码

private void initViewGroup() {……// 初始化保存当前ViewGroup中所有View的数组mChildren = new View[ARRAY_INITIAL_CAPACITY];// 初始时其Child个数为0mChildrenCount = 0;……}

视图的创建过程的都会执行的三个步骤: onMeasure, onLayout, onDraw

二、接着2 即 ListView.onMeasure方法,只是获取当前ListView的宽高 @Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {// Sets up mListPaddingsuper.onMeasure(widthMeasureSpec, heightMeasureSpec);// 获取当前ListView总宽高int widthSize = MeasureSpec.getSize(widthMeasureSpec);int heightSize = MeasureSpec.getSize(heightMeasureSpec);……setMeasuredDimension(widthSize , heightSize);mWidthMeasureSpec = widthMeasureSpec;}三、步骤3是重点,AbsListView.onLayout的流程与普通View的不同 @Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b) {super.onLayout(changed, l, t, r, b);mInLayout = true;// 初始时changed = trueif (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);}// ListView实现此方法layoutChildren();mInLayout = false;mOverscrollMax = (b – t) / OVERSCROLL_LIMIT_DIVISOR;}四、步骤4.1 具体分析ListVIew.layoutChildren @Overrideprotected void layoutChildren() {// 默认为falsefinal boolean blockLayoutRequests = mBlockLayoutRequests;if (!blockLayoutRequests) {// 目的是为了阻止没必要的layout操作,提交效率mBlockLayoutRequests = true;} else {return;}try {super.layoutChildren();// 为什么此处要请求重绘?invalidate();……int childCount = getChildCount();……boolean dataChanged = mDataChanged;if (dataChanged) {handleDataChanged();}……// 把所有child view放置到RecycleBin// 满足条件的话可以重用这些child viewfinal int firstPosition = mFirstPosition;// ListView中Item复用使用此数据结构final RecycleBin recycleBin = mRecycler;// reset the focus restorationView focusLayoutRestoreDirectChild = null;// Don’t put header or footer views into the Recycler. Those are// already cached in mHeaderViews;if (dataChanged) {for (int i = 0; i < childCount; i++) {recycleBin.addScrapView(getChildAt(i), firstPosition+i);}} else {// 创建childCount个数的View放入RecycleBin类activeViews数组中recycleBin.fillActiveViews(childCount, firstPosition);}……// Clear out old viewsdetachAllViewsFromParent();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;}// Flush any cached views that did not get reused aboverecycleBin.scrapActiveViews();……invokeOnItemScrollListener();} finally {if (!blockLayoutRequests) {mBlockLayoutRequests = false;}}

五、 分析步骤4.2 ListView.fillFromTop源码

// 从上向下在ListView中填充Item Viewprivate 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源码 // 在参数pos下面填充Item Viewprivate View fillDown(int pos, int nextTop) {View selectedView = null;// ListView getHeight也是这样计算的int end = (mBottom – mTop);if ((mGroupFlags & CLIP_TO_PADDING_MASK) == CLIP_TO_PADDING_MASK) {end -= mListPadding.bottom;}// 初始化时pos = 0,如果item总数少于一屏幕,执行mItemCount – pos次// 如果item多余一屏幕,执行end – nextTop次while (nextTop < end && pos < mItemCount) {// is this the selected item?boolean selected = pos == mSelectedPosition;// 获取Item View对象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;}用最少的浪费面对现在

Android ListView初始化简单分析

相关文章:

你感兴趣的文章:

标签云: