1. 程式人生 > >Android ListView介面卡中的getView()被複用詳解

Android ListView介面卡中的getView()被複用詳解

在這之前,申明下,這篇屬於總結一些網上的內容加自己實踐證明。

ListView顯示資料時,自定義了一個介面卡(extends BaseAdapter,然後重寫了getView方法,現在出現一個問題,就是這個getView()方法:

 

被重複呼叫了;

比如我的_data中有兩條資料,但是getView()方法 卻被執行了四次甚至更多,請問這是神馬情況?

這是什麼樣的情況,看了網上的資料以後我知道原來沒有設定器listview 的佈局方式不是fill-parent,而是wrap-content,會計算父控制元件的高度所以造成了一種反覆呼叫情況,從而次數不確定。

更深層次的解釋為:

View

Draw的時候分成兩個階段:measurelayout,在measure階段時主要就是為了計算兩個引數:heightwidth。而且要注意的是,這是個遞迴的過程,從頂向下,DecorView開始依次呼叫自己子元素的measure。計算完成這兩個引數後就開始layout,最後再是draw的呼叫。

對於ListView,當然每一個Item都會被呼叫measure方法,而在這個過程中getViewgetCount會被呼叫,而且看使用者的需求,可能會有很多次呼叫。

而為什麼會有很多組次呼叫呢?

問題就在於在layout中的決定ListView或者它的父元素的heightwidth屬性的定義了。

fill_parent會好一點,計算方法會比較簡單,只要跟父元素的大小相似就行,但是即使是fill_parent,也不能給View當飯吃,還是要計算出來具體的dip,所以measure還是會被呼叫,只是可能比wrap_content的少一點。至於自適應的它會一直考量它的寬和高,根據內容(也就是它的子Item)計算寬高。可能這個measure過程會反覆執行,如果父元素也是wrap_content,這個過程會更加漫長。

所以,解決方法就是儘量避免自適應,除非是萬不得已,固定大小或者填充的效果會比較好一些。

具體例子詳介:

 

1、xml佈局沒有寫成固定高度/fill_cntent/match_parent

時;



執行結果:


不難看出,getView()一共執行了4輪,已經複用多輪;


2、寫成固定高度/fill_cntent/match_parent時:



執行結果:

 

現在,getView()只執行了1輪;也是我們需要的結果;

以上對比就可以看出我們需要怎麼去處理;

如果複用多次,在 介面卡顯示圖片 或 點選事件 的時候,可能會導致position錯亂,從而重新整理顯示的時候:(不對應)錯位現象!

另外一個帶提到的,也是listView這類帶快取控制元件顯示的優點:

如果資料很多條(list.size()),超出螢幕很多(具體是多少沒細究);listView的只會先執行一部分的getView()方法(應該就螢幕內的資料數次)而不會上來就執行list.size()全部資料的總次數;當你下滑時,getView()方法才會繼續執行一部分......(其實就是listView快取機制)哈哈....結合這個例子去看這個快取機制,效果會好很多哦!

無奈的補充下,listView被巢狀的時候,如上:父listView追尋上述方法;子listView不管怎麼設定,還是會複用多次....我也測試了好久沒找到好方法(問大神,度娘什麼的),如果有大神知道,可以分享下...