StaggeredGridView 实现分析--首次填充过程(一)

ExtendableListView.java

1, 因为是首次layout, changed为true, childCount是 0, 

//ExtendableListView.java
/**
     * {@inheritDoc}
     */
    @Override
    protected void onLayout(final boolean changed, final int l, final int t, final int r, final int b) {
        // super.onLayout(changed, l, t, r, b); - skipping base AbsListView implementation on purpose
        // haven't set an adapter yet? get to it
        if (mAdapter == null) {
            return;
        }

        if (changed) {
            int childCount = getChildCount();
            for (int i = 0; i < childCount; i++) {
                getChildAt(i).forceLayout();
            }
            mRecycleBin.markChildrenDirty();
        }

        // TODO get the height of the view??
        mInLayout = true;
        layoutChildren();
        mInLayout = false;
    }

2, layoutChildren, 在步骤1中可知 在layoutChildren()期间 变量mInLayout 一直为true。

在attachToWindow() 和 setAdapter(..)时 ,如果adapter不为null, 则mDataChanged 设置为 true, 所以假设这里的mDataChanged是true .

在handleDataChanged() 中, mLayoutMode 被设置为 LAYOUT_FORTCE_TOP , 所以 mFirstPosition 为 0, 然后执行 fillFromTop( top) ,假设没有headerview, 那么 top值是0 或者 listview的 topPadding值。

//ExtendableListView.java
/**
     * {@inheritDoc}
     */
    @Override
    protected void layoutChildren() {
        if (mBlockLayoutRequests) return;
        mBlockLayoutRequests = true;

        try {
            super.layoutChildren();
            invalidate();

           ...
           
            int childrenTop = getListPaddingTop();

            int childCount = getChildCount();
            View oldFirst = null;

            // our last state so we keep our position
            if (mLayoutMode == LAYOUT_NORMAL) {
                oldFirst = getChildAt(0);
            }

            boolean dataChanged = mDataChanged;
            if (dataChanged) {
                handleDataChanged();
            }

            ...
            
            // Pull all children into the RecycleBin.
            // These views will be reused if possible
            final int firstPosition = mFirstPosition;
            final RecycleBin recycleBin = mRecycleBin;

            if (dataChanged) { // true now
                for (int i = 0; i < childCount; i++) { // childcount is 0 now
                    recycleBin.addScrapView(getChildAt(i), firstPosition + i);
                }
            }
            else {
                recycleBin.fillActiveViews(childCount, firstPosition);
            }

            // Clear out old views
            detachAllViewsFromParent();
            recycleBin.removeSkippedScrap();

            switch (mLayoutMode) {
                case LAYOUT_FORCE_TOP: {
                    mFirstPosition = 0;
                    resetToTop();
                    adjustViewsUpOrDown();
                    fillFromTop(childrenTop);
                    adjustViewsUpOrDown();
                    break;
                }
                case LAYOUT_SYNC: {
                    fillSpecific(mSyncPosition, mSpecificTop);
                    break;
                }
                case LAYOUT_NORMAL:
                default: {
                    if (childCount == 0) {
                        fillFromTop(childrenTop);
                    }
                    else if (mFirstPosition < mItemCount) {
                        fillSpecific(mFirstPosition,
                                oldFirst == null ? childrenTop : oldFirst.getTop());
                    }
                    else {
                        fillSpecific(0, childrenTop);
                    }
                    break;
                }
            }

            // Flush any cached views that did not get reused above
            recycleBin.scrapActiveViews();
            mDataChanged = false;
            mNeedSync = false;
            mLayoutMode = LAYOUT_NORMAL;
            invokeOnItemScrollListener();
        } finally {
            mBlockLayoutRequests = false;
        }
    }

    ////////////////////////////////////////////////////////

2' , override:

这里将mColumnBottoms[] 和 mColumnTops[]是一样的值(每个值都是0, 或者listview的 topPadding值), 因为还没任何child view

//StaggeredGridView.java
    @Override
    protected void layoutChildren() {
        preLayoutChildren();
        super.layoutChildren();
    }
    
    //mNeedSync 在 onRestoreInstanceState 时才会被设置为true,其他情况均为false
    private void preLayoutChildren() {
        // on a major re-layout reset for our next layout pass
        if (!mNeedSync) {
            Arrays.fill(mColumnBottoms, 0);
        }
        else {
            mNeedSync = false;
        }
        // copy the tops into the bottom
        // since we're going to redo a layout pass that will draw down from
        // the top
        System.arraycopy(mColumnTops, 0, mColumnBottoms, 0, mColumnCount);
    }

3, 回顾2, ExtendableListView.java, fillFromTop, 其参数是0 或者 listView的 topPadding值;mFirstPosition是0

在fillDown中, 此时 itemPos 是0 ; nextTop是顶部位置: topPadding 或 0 , 通过while循环这一过程,将有足够多的child view 被生成以填满整个listview。

//ExtendableListView.java

/**
     * Fills the list from top to bottom, starting with mFirstPosition
     */
    private View fillFromTop(int nextTop) {
        mFirstPosition = Math.min(mFirstPosition, mItemCount - 1);
        if (mFirstPosition < 0) {
            mFirstPosition = 0;
        }
        return fillDown(mFirstPosition, nextTop);
    }
    
    private View fillDown(int itemPos, int nextTop) { //(0,topPadding)
        if (DBG) Log.d(TAG, "fillDown - pos:" + pos + " nextTop:" + nextTop);

        View selectedView = null;

        int end = getHeight();
        if (mClipToPadding) {
            end -= getListPaddingBottom();
        }

        while ((nextTop < end || hasSpaceDown()) && pos < mItemCount) {
            // TODO : add selection support
            // 目前不支持select , 所以selected一律为false
            makeAndAddView(itemPos, nextTop, true, false);
            itemPos++;
            nextTop = getNextChildDownsTop(itemPos); // = child.getBottom();
        }

        return selectedView;
    }

4, makeAndAddView(0, 0, true, false):

执行obtainView

//ExtendableListView.java
 /**
     * Gets a view either a new view an unused view?? or a recycled view and adds it to our children
     */
    private View makeAndAddView(int position, int y, boolean flowDown, boolean selected) {
        View child;

        onChildCreated(position, flowDown);

        if (!mDataChanged) {// now mDataChanged is true , so it is skipped here
            // Try to use an existing view for this position
            child = mRecycleBin.getActiveView(position);
            if (child != null) {

                // Found it -- we're using an existing child
                // This just needs to be positioned
                setupChild(child, position, y, flowDown, selected, true);
                return child;
            }
        }

        // Make a new view for this position, or convert an unused view if possible
        child = obtainView(position, mIsScrap);
        // This needs to be positioned and measured
        setupChild(child, position, y, flowDown, selected, mIsScrap[0]);

        return child;
    }

4.1 onChildCreated( 0, true): ExtendableListView 的实现为空, 所以直接看StaggeredGridView的实现:

执行if 部分,需要看 getChildColumn 和 setPositionColumn 。

 //StaggeredGridView.java
  
   @Override
    protected void onChildCreated(final int position, final boolean flowDown) {
        super.onChildCreated(position, flowDown);
        if (!isHeaderOrFooter(position)) {
            // do we already have a column for this position?
            final int column = getChildColumn(position, flowDown);
            setPositionColumn(position, column); 
        }
        else {
            setPositionIsHeaderFooter(position);
        }
    }


你可能感兴趣的:(StaggeredGridView 实现分析--首次填充过程(一))