Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android ListView 在初始化時多次調用getView()原因分析

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

編輯:關於Android編程

今天在做一個功能:在初始化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時,不會成立。
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved