ListView原理简单介绍(着重介绍getView被调用的一系列过程)
好了,重點(diǎn)在第三行,我將Adapter的getView方法所傳回的ViewGroup parent對(duì)象放置到了inflate的第二個(gè)參數(shù)中使用,inflate的第三個(gè)參數(shù)為true,面試官當(dāng)時(shí)問(wèn)的就是會(huì)出現(xiàn)什么問(wèn)題,現(xiàn)在運(yùn)行一下,看Log:
出了java.lang.UnsupportedOperationException: addView(View, LayoutParams) is not supported in AdapterView的異常,我們看一下問(wèn)題出在哪:
首先,要看從getView第三個(gè)參數(shù)回調(diào)傳回來(lái)的是什么,我們來(lái)看源碼:
既然是adapter與AbsListView結(jié)合使用,那getView方法一定是在AbsListView中被使用的,來(lái)找一找:
首先該怎么找呢?咱們都知道AbsListView通過(guò)setAdapter方法使兩者結(jié)合,那么入口就在這里:
@Overridepublic 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);通過(guò)第13行可以知道adapter對(duì)象是賦給了mAdapter,通過(guò)查看mAdapter是父類的屬性,那咱們就需要在父類中看什么時(shí)候使用了mAdaper.getView方法:
果然找到了,在AbsListView的obtainView方法中找到了getView方法被使用的情況:
View obtainView(int position, boolean[] isScrap) {isScrap[0] = false;View scrapView;scrapView = mRecycler.getTransientStateView(position);if (scrapView != null) {return scrapView;}scrapView = mRecycler.getScrapView(position);View child;if (scrapView != null) {child = mAdapter.getView(position, scrapView, this);if (child.getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {child.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);}if (child != scrapView) {mRecycler.addScrapView(scrapView, position);if (mCacheColorHint != 0) {child.setDrawingCacheBackgroundColor(mCacheColorHint);}} else {isScrap[0] = true;child.dispatchFinishTemporaryDetach();}} else {child = mAdapter.getView(position, null, this);通過(guò)第14行和最后一行可知,它是將AbsListView的實(shí)現(xiàn)類傳了過(guò)來(lái)。
那好,就回到?inflater.inflate(R.layout.activity_main, parent, true);這里,繼續(xù)向下看:
public View inflate(int resource, ViewGroup root, boolean attachToRoot) {if (DEBUG) System.out.println("INFLATING from resource: " + resource);XmlResourceParser parser = getContext().getResources().getLayout(resource);try {return inflate(parser, root, attachToRoot);} finally {parser.close();}}這里調(diào)用了重載方法 inflate(parser, root, attachToRoot);在重載方法內(nèi)部我們看到:
// We are supposed to attach all the views we found (int temp)// to root. Do that now.if (root != null && attachToRoot) {root.addView(temp, params);}
也就是說(shuō)把自定義的這個(gè)Item附加到了AbsListView上,好。接下來(lái)看getView被返回的View被用作在了什么地方,它目前已經(jīng)有parent了。
還是需要回到AbsListView.obtainView方法,通過(guò)第14行可以看到這個(gè)通過(guò)getView方法返回的View最終被obtainView彈了出去,繼續(xù)看,由于在AbsListView中沒(méi)有找到使用obtainView的地方,所以使用obtainView的地方應(yīng)該在其子類中,果不其然(這里通過(guò)ListView做演示):
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {// Sets up mListPaddingsuper.onMeasure(widthMeasureSpec, heightMeasureSpec);int widthMode = MeasureSpec.getMode(widthMeasureSpec);int heightMode = MeasureSpec.getMode(heightMeasureSpec);int widthSize = MeasureSpec.getSize(widthMeasureSpec);int heightSize = MeasureSpec.getSize(heightMeasureSpec);int childWidth = 0;int childHeight = 0;int childState = 0;mItemCount = mAdapter == null ? 0 : mAdapter.getCount();if (mItemCount > 0 && (widthMode == MeasureSpec.UNSPECIFIED ||heightMode == MeasureSpec.UNSPECIFIED)) {final View child = obtainView(0, mIsScrap);
我們?cè)谧詈笠恍锌吹搅薿btainView的身影,它被用來(lái)做什么呢?既然是onMeasure方法,那就是測(cè)量唄,沒(méi)什么好說(shuō)的,再繼續(xù)看,在ListView中發(fā)現(xiàn)5處obtainView被調(diào)用的地方,其中兩處用于測(cè)量,剩余3處通過(guò): private void setupChild(View child, int position, int y, boolean flowDown, int childrenLeft,boolean selected, boolean recycled)這個(gè)方法將obtainView返回的View傳了進(jìn)來(lái),最終我們可以在該方法內(nèi)部看到這么一段代碼,是屬于ViewGroup的:
attachViewToParent(child, flowDown ? -1 : 0, p);
---未完待續(xù)---
總結(jié)
以上是生活随笔為你收集整理的ListView原理简单介绍(着重介绍getView被调用的一系列过程)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 暑期实习NLP算法岗面经总结
- 下一篇: 【Tensorflow】小白入门实战基础