android ListView 在初始化時多次調用getView()原因分析


   今天在做一個功能:在初始化ListView時,把第一行背景置為黃色,同時保存第一行對象,用於在點擊其他行時將該行重新置為白色。

if(position==0){
                convertView.setBackgroundColor(Color.YELLOW);
                lastconvertView=convertView;
            }

 

結果運行時發現第一行的顏色一直會是黃色而無法改變。調試了之后發現getView中 if(position==0) 居然會多次進入,最終導致的結果便是我最后一次取得的lastconvertView並非listview上面的第一行。網上查了之后發現原因是因為未固定listview的高度導致的,但是root cause卻找不到說明。於是去翻閱了源碼+大量調試,大概推算出了原因,在此記錄。

首先是說明下ListView的顯示機制,listview的機制是這樣子的:

假如你有1000條數據,但是屏幕只能顯示10條,那么當你第一次加載顯示的時候,會先創建10個View,1-10,當你拖動Listview,使1隱藏而11顯示的時候,系統會自動把填充1的View傳遞過來,注意看代碼Adapter的getView方法

@Override
public View getView(final int position, View convertView, ViewGroup parent) 

這里的converView就是1的view,一般的做法會把這個view拿來復用,作為11的view。

 

當我們固定listview的高度時(fill_parent或直接固定高度),那么listview很容易就能計算出容器內可以顯示多少行。但如果我們使用了“wrap_content”,只有在屏幕內控件完全加載后才知道到底能顯示多少行數據時,ListView自身便會做一些嘗試性計算。在源碼中可以發現一些叫做onMeasure的方法,目測是做此用處(源碼略顯復雜,沒讀透)。

當listview計算出屏幕一共需要多少行后,如果listview自身高度不變,那么它的容納的行數就不會變,使用getChildCount()可以得到它的最大行數。

再回到原來的問題,為什么最后一次取得的結果不是listview的第一行呢? 將listview設置為“wrap_content”后用下面的測試代碼,看下輸出。

//獲取當前listview的個數 相等輸出個數和站點名 不相等輸出個數和"無"
            if(listView.getChildCount() == position)
            {
                //child個數 當前position位置 +站名
                Log.i("", listView.getChildCount()+" "+position+" "+coordInfo.stationname);
            }
            else {
                //child個數 當前position位置+無
                Log.i("", listView.getChildCount()+" "+position+" "+"無");
            }

在我的測試應用中,listview剛好可以放11個view,看下輸出發現,listview在開始時,實例化了11個view進行填充,即前面10個“無”結尾的+第一個”客運中心“結尾的view,由此測量出了listview的容量。換句話說,這11個view都只是用於測量的臨時view。另外在正是填充完之后,listview再次創建了11個臨時view用於確認高度是否正確。而由於我的代碼邏輯設計失誤,在

進行到這一步時,由於position會再次等於0,因此會把一個臨時的view賦值給lastconvertView。

到此原因找到,同時將listview的高度設為fill_parent后,問題解決。

 

另外說下網上說的另外一個解決方法

if(parent.getchildcount() == position)
{
       正常情況下應該執行的代碼
}
else
{
     這里就是多次加載的問題,可以不用理這里面的 代碼,
}

這個方法是不可行的,因為在不改變listview高度的情況下,listview的getchildcount()在加載完成后是固定的,position指的卻是在adapter中的位置,當adapter的個數大於listview的容納個數時,該判斷條件不會成立,即滑動listview時,不會成立。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM