ListActivity和ListView源碼分析(1) 載入布局,listview載入網狀圖片

來源:互聯網
上載者:User

ListActivity和ListView源碼分析(1) 載入布局,listview載入網狀圖片

最近寫代碼總是用到ListActivity,因此看了下ListView和ListActivity的原始碼.

1 載入布局

一般來說我們使用自訂的ListActivity時,在建立時首先需要調用setContentView函數來設定這個Activity對應的view布局.

而從Activity.onContentChanged()的api文檔說明來看,setContentView方法會導致onContentChanged方法被調用.因此我們接下來來看下ListActivity的onContentChanged方法.

    public void onContentChanged() {        super.onContentChanged();        View emptyView = findViewById(com.android.internal.R.id.empty);        mList = (ListView)findViewById(com.android.internal.R.id.list);        if (mList == null) {            throw new RuntimeException(                    "Your content must have a ListView whose id attribute is " +                    "'android.R.id.list'");        }        if (emptyView != null) {            mList.setEmptyView(emptyView);        }        mList.setOnItemClickListener(mOnClickListener);        if (mFinishedStart) {            setListAdapter(mAdapter);        }        mHandler.post(mRequestFocus);        mFinishedStart = true;    }
1.1 R.id.list 擷取ListView

我們可以看到這裡取了兩個固定ID的view,一個是R.id.empty,一個是R.id.list.
R.id.list對應Activity中的listview,這也是為什麼官方文檔(參看前一篇文檔)中寫道”確保你自訂的Layout包含一個id為”@android:id/list”的ListView”.我們也可以看到如果系統取不到R.id.list對應的view,會直接拋出異常.得到的這個view將儲存在mList中.

1.2 R.id.empty 擷取空視圖

而R.id.empty在官方文檔中也有提到,這view將會在list view為空白時顯示.
因為mList剛剛擷取得到,因此此時肯定為空白,一旦我們得到這個empty view,立刻調用ListView的setEmptyView函數:

    public void setEmptyView(View emptyView) {        mEmptyView = emptyView;        // If not explicitly specified this view is important for accessibility.        if (emptyView != null                && emptyView.getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {            emptyView.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);        }        final T adapter = getAdapter();        final boolean empty = ((adapter == null) || adapter.isEmpty());        updateEmptyStatus(empty);    }

這個時候adapter尚未設定所以肯定為空白,所以empty為true.
updateEmptyStatus主要是設定一些可見度之類的參數.

1.3 setOnItemClickListener註冊點擊回調

接下來onContentChanged函數調用了ListView的setOnItemClickListener方法註冊每個item的點擊回調監聽類mOnClickListener.

    private AdapterView.OnItemClickListener mOnClickListener = new AdapterView.OnItemClickListener() {        public void onItemClick(AdapterView<?> parent, View v, int position, long id)        {            onListItemClick((ListView)parent, v, position, id);        }    };

我們看到這裡調用了方法onListItemClick,這也就是為什麼我們希望在自訂的ListActivity中監聽每個item的點擊方法時,必須重載父類中的onListItemClick方法.

1.4 mFinishedStart

回到ListActivity的onContentChanged函數中來,mFinishedStart參數起到了這樣一個作用.
當這個Activity被最初建立時,mFinishedStart值為false.因此這個時候自然也不需要設定adapter.而在onContentChanged函數被調用過一次之後, mFinishedStart變為true.這保證了在後面已經設定了adapter之後,一旦內容變化,adapter不需要再次被使用者手動設定.

最後mHandler.post(mRequestFocus);通知父類mList可以獲得焦點.至此,setContentView方法結束.

2 setListAdapter設定adapter

後面我們使用ListActivity一般就會調用方法setListAdapter,設定對應的adapter用於給ListView提供資料.這個函數涉及到了ListView和Adapter互動的過程,我們將在下一章節詳細講述.

  public void setAdapter(ListAdapter adapter) {        if (mAdapter != null && mDataSetObserver != null) {            mAdapter.unregisterDataSetObserver(mDataSetObserver);        }        resetList();        mRecycler.clear();        if (mHeaderViewInfos.size() > 0|| mFooterViewInfos.size() > 0) {            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();            mAdapter.registerDataSetObserver(mDataSetObserver);            mRecycler.setViewTypeCount(mAdapter.getViewTypeCount());            int position;            if (mStackFromBottom) {                position = lookForSelectablePosition(mItemCount - 1, false);            } else {                position = lookForSelectablePosition(0, true);            }            setSelectedPositionInt(position);            setNextSelectedPositionInt(position);            if (mItemCount == 0) {                // Nothing selected                checkSelectionChanged();            }        } else {            mAreAllItemsSelectable = true;            checkFocus();            // Nothing selected            checkSelectionChanged();        }        requestLayout();    }

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.