listview 部分代码分析

来源:互联网 发布:web数据挖掘的概念 编辑:程序博客网 时间:2024/05/23 15:48
/**     * Sets the data behind this ListView.     *     * The adapter passed to this method may be wrapped by a {@link WrapperListAdapter},     * depending on the ListView features currently in use. For instance, adding     * headers and/or footers will cause the adapter to be wrapped.     *     * @param adapter The ListAdapter which is responsible for maintaining the     *        data backing this list and for producing a view to represent an     *        item in that data set.     *     * @see #getAdapter()      */    @Override    public void setAdapter(ListAdapter adapter) {        if (mAdapter != null && mDataSetObserver != null) {            mAdapter.unregisterDataSetObserver(mDataSetObserver);//移除了与当前listview的adapter绑定数据集观察者DataSetObserver        }        resetList();//重置listview,主要是清除所有的view,改变header、footer的状态        mRecycler.clear();    //清除掉RecycleBin对象mRecycler中所有缓存的view,RecycleBin后面着重介绍,主要是关系到Listview中item的重用机制,它是AbsListview的一个内部类        if (mHeaderViewInfos.size() > 0|| mFooterViewInfos.size() > 0) {   //判断是否有headerview和footview            mAdapter = new HeaderViewListAdapter(mHeaderViewInfos, mFooterViewInfos, adapter);        } else {            mAdapter = adapter;        }        mOldSelectedPosition = INVALID_POSITION;        mOldSelectedRowId = INVALID_ROW_ID;        // AbsListView#setAdapter will update choice mode states.        super.setAdapter(adapter);        if (mAdapter != null) {            mAreAllItemsSelectable = mAdapter.areAllItemsEnabled();            mOldItemCount = mItemCount;            mItemCount = mAdapter.getCount();            checkFocus();            mDataSetObserver = new AdapterDataSetObserver(); //注册headerview的观察者            mAdapter.registerDataSetObserver(mDataSetObserver);//在RecycleBin对象mRecycler记录下item类型的数量            mRecycler.setViewTypeCount(mAdapter.getViewTypeCount());            int position;            if (mStackFromBottom) {                position = lookForSelectablePosition(mItemCount - 1, false);            } else {                position = lookForSelectablePosition(0, true);            }                         setSelectedPositionInt(position);//AdapterView中的方法,记录当前的position             setNextSelectedPositionInt(position);//AdapterView中的方法,记录下一个position            if (mItemCount == 0) {                // Nothing selected                checkSelectionChanged();            }        } else {            mAreAllItemsSelectable = true;            checkFocus();            // Nothing selected            checkSelectionChanged();        }        requestLayout();    }    /**     * Obtain the view and add it to our list of children. The view can be made     * fresh, converted from an unused view, or used as is if it was in the     * recycle bin.     *     * @param position Logical position in the list     * @param y Top or bottom edge of the view to add     * @param flow If flow is true, align top edge to y. If false, align bottom     *        edge to y.     * @param childrenLeft Left edge where children should be positioned     * @param selected Is this position selected?     * @return View that was added     */    private View makeAndAddView(int position, int y, boolean flow, int childrenLeft,            boolean selected) {        View child;        if (!mDataChanged) {            // Try to use an existing view for this position            child = mRecycler.getActiveView(position);                //首先是从已经回收的的view中重新激活             if (child != null) {                if (ViewDebug.TRACE_RECYCLER) {                    ViewDebug.trace(child, ViewDebug.RecyclerTraceType.RECYCLE_FROM_ACTIVE_HEAP,                            position, getChildCount());                }                // Found it -- we're using an existing child                // This just needs to be positioned                setupChild(child, position, y, flow, childrenLeft, selected, true);                return child;            }        }        //下面是listview中获取重用view的机制        // 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, flow, childrenLeft, selected, mIsScrap[0]);        return child;    } /**     * Get a view and have it show the data associated with the specified     * position. This is called when we have already discovered that the view is     * not available for reuse in the recycle bin. The only choices left are     * converting an old view or making a new one.     *     * @param position The position to display     * @param isScrap Array of at least 1 boolean, the first entry will become true if     *                the returned view was taken from the scrap heap, false if otherwise.     *     * @return A view displaying the data associated with the specified position     */    View obtainView(int position, boolean[] isScrap) {        isScrap[0] = false;        View scrapView;        scrapView = mRecycler.getScrapView(position);         //首先是从回收站进行检查,找到相应位置的被回收的        View child;        if (scrapView != null) {            if (ViewDebug.TRACE_RECYCLER) {                ViewDebug.trace(scrapView, ViewDebug.RecyclerTraceType.RECYCLE_FROM_SCRAP_HEAP,                        position, -1);            }            child = mAdapter.getView(position, scrapView, this);            if (ViewDebug.TRACE_RECYCLER) {                ViewDebug.trace(child, ViewDebug.RecyclerTraceType.BIND_VIEW,                        position, getChildCount());            }            if (child != scrapView) {                        //如果重用的view和adapter获得的view是不一样的,将scrapView进行回收                mRecycler.addScrapView(scrapView, position);                if (mCacheColorHint != 0) {                    child.setDrawingCacheBackgroundColor(mCacheColorHint);                }                if (ViewDebug.TRACE_RECYCLER) {                    ViewDebug.trace(scrapView, ViewDebug.RecyclerTraceType.MOVE_TO_SCRAP_HEAP,                            position, -1);                }            } else {                isScrap[0] = true;                            //如果重用的view和adapter获得的view是一样的,将isScrap[0]值为true,否则默认为false                 child.dispatchFinishTemporaryDetach();            }        } else {            child = mAdapter.getView(position, null, this);   //当getview中为null的时候会在getview的方法中进行新建这个view            if (mCacheColorHint != 0) {                child.setDrawingCacheBackgroundColor(mCacheColorHint);            }            if (ViewDebug.TRACE_RECYCLER) {                ViewDebug.trace(child, ViewDebug.RecyclerTraceType.NEW_VIEW,                        position, getChildCount());            }        }        return child;    } 


原创粉丝点击