ListView是Android布局中常用的控件之一,用于顯示列表的效果都要使用ListView,下面是android開(kāi)發(fā)中ListView與Adapter的使用要點(diǎn),跟著武林技術(shù)頻道小編帶你來(lái)了解一下吧!
1. Adapter.getView() public View getView(int position, View convertView , ViewGroup parent){...}
這個(gè)方法就是用來(lái)獲得指定位置要顯示的View。官網(wǎng)解釋如下:
Get a View that displays the data at the specified position in the data set. You can either create a View manually or inflate it from an XML layout file.
當(dāng)要顯示一個(gè)View就調(diào)用一次這個(gè)方法。這個(gè)方法是ListView性能好壞的關(guān)鍵。方法中有個(gè)convertView,這個(gè)是Android在為我們而做的緩存機(jī)制。
ListView中每個(gè)item都是通過(guò)getView返回并顯示的,假如item有很多個(gè),那么重復(fù)創(chuàng)建這么多對(duì)象來(lái)顯示顯然是不合理。因此,Android提供了Recycler,將沒(méi)有正在顯示的item放進(jìn)RecycleBin,然后在顯示新視圖時(shí)從RecycleBin中復(fù)用這個(gè)View。
Recycler的工作原理大致如下:
假設(shè)屏幕最多能看到11個(gè)item,那么當(dāng)?shù)?個(gè)item滾出屏幕,這個(gè)item的View進(jìn)入RecycleBin中,第12個(gè)要出現(xiàn)前,通過(guò)getView從回收站(RecycleBin)中重用這個(gè)View,然后設(shè)置數(shù)據(jù),而不必重新創(chuàng)建一個(gè)View。
我們用Android提供的APIDemos來(lái)驗(yàn)證這個(gè)過(guò)程:
先看關(guān)鍵代碼:
效果圖:

可以看到,一打開(kāi)Activity,看到10個(gè)item.
我們看看Log信息:

可以看出,每次convertView都是null, 都是新建一個(gè)View來(lái)顯示的。
當(dāng)我們向下滑動(dòng),如下圖,

由于item0和item10都顯示一半,所以item10也是新建出來(lái),但是當(dāng)要顯示item11的時(shí)候,由于item0已經(jīng)不在屏幕上,所以item11復(fù)用了item0的實(shí)例。可以從以下Log信息看出:

我們分析Log信息,可以看出item11的對(duì)象是item0, item12的對(duì)象是item1,如此類(lèi)推。
這樣,通過(guò)復(fù)用convertView,就可以避免每次都新建View,節(jié)省內(nèi)存而且優(yōu)化ListView的滑動(dòng)效果。
2. ListView的Layout XML
除了上述說(shuō)的,還有一個(gè)要點(diǎn)就是ListView在Layout XML中的描述。
先看問(wèn)題:
有時(shí),我們可能會(huì)看到一打開(kāi)ListView,getView會(huì)重復(fù)調(diào)用好次(假設(shè)屏幕最多可以看到6個(gè)item),如下圖:

一直重復(fù) 0-6, 0-5,0-5, 0-5,0-5, 0-5。而且,convertView一開(kāi)始都是同一個(gè)View,這個(gè)是因?yàn)長(zhǎng)istView的
android:layout_height="wrap_content"。
我們修改為android:layout_height="fill_parent",Log信息如下:

可以看出,修改之后ListView的getView調(diào)用恢復(fù)和Recycler的行為一致。
至于為什么使用wrap_content會(huì)出現(xiàn)重復(fù)調(diào)用的情況,我還沒(méi)有研究過(guò)。不過(guò)初步覺(jué)得是因?yàn)樵贏ndroid描繪ListView的時(shí)候,由于不清楚高度,所以使用一個(gè)item去試探ListView在屏幕中的最大高度所引起。希望有知道的朋友能夠告訴,先謝謝了!
最后,如果上面有什么地方說(shuō)錯(cuò)的話(huà),希望能夠指出,互相進(jìn)步嘛。
補(bǔ)充:
在接著使用ListView的時(shí)候,又發(fā)現(xiàn)一個(gè)很奇怪的現(xiàn)象。調(diào)用notifyDataSetChanged()之后,ListView在重新getView()時(shí),所有的convertView的順序都逆序了。請(qǐng)看下面截圖:

這應(yīng)該是由于recycleBin是stack結(jié)構(gòu)而引起。
其它:
1. Disable divider:
android:divider="#00000000"
android:dividerHeight="0dp"
2. Disable ListView selector:
convertView.setOnClickListener(null);
如果只是要去掉顏色,可以用android:listSelector="#00000000"
3. Disable header divider:
android:headerDividersEnabled="false"
4. getItemViewType(int)與getItemViewType(int)
getItemViewType(int) can not return int value larger than getViewTypeCount().
Otherwise you will get java.lang.ArrayIndexOutOfBoundsException at android.widget.AbsListView$RecycleBin.addScrapView(AbsListView.java:3523)
ListView會(huì)根據(jù)不同的ViewType返回相應(yīng)type的convertView.
一般寫(xiě)法:
通過(guò)武林技術(shù)頻道小編介紹的內(nèi)容,相信大家都有了一定的了解,想要了解更多的技術(shù)內(nèi)容,請(qǐng)繼續(xù)關(guān)注武林技術(shù)頻道吧!
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注