首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

Android ListView getView 重複調用根因與解決:Measure 階段與布局屬性的關鍵影響

     編輯:關於.NET

自定義 ArrayAdapter 重寫 getView() 時,發現兩筆資料卻觸發 4 次以上呼叫,甚至更多。深入探討後發現,核心在於 ListView 與其父容器的 layout_width/height 設定為 wrap_content 導致多次 measure 遞歸計算,進而反覆觸發 getView 以取得子視圖尺寸。

問題代碼片段

public class CustomCollectAdapter extends ArrayAdapter<House> {
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        // ... ViewHolder 模式、異步載圖、按鈕事件等標準邏輯
        System.out.println(house.toString()); // 此行重複打印
        return view;
    }
}

核心原理:Measure 階段的遞歸計算

Android 視圖繪製分 Measure → Layout → Draw 三階段。ListView 在 Measure 階段需計算自身高度,若父容器也是 wrap_content,則形成雙向依賴:

  • fill_parent:尺寸確定,Measure 呼叫較少。
  • wrap_content:需遞歸詢問每個 Item 高度,getView 被頻繁調用以測量尺寸。
  • 巢狀 wrap_content:Measure 過程可能反覆迭代,導致調用次數不可控。

解決方案

  1. 將 ListView 或其父容器高度設為 match_parent / 固定 dp(最根治)
  2. 若必須自適應,嘗試在 onMeasure 中快取尺寸或限制測量模式
  3. 避免在 getView 執行耗時邏輯(如複雜運算、IO),改用異步載圖、ViewHolder 快取

異步載圖實作參考

代碼中採用 AsyncTask + SoftReference 快取圖片,避免 OOM:

public class AsyncImageLoaderTask extends AsyncTask<Object, Object, Bitmap> {
    private HashMap<String, SoftReference<Bitmap>> imageCache = new HashMap<>();
    @Override
    protected Bitmap doInBackground(Object... params) {
        String url = (String) params[0];
        ImageView view = (ImageView) params[1];
        // 先查快取,再下載,最後存入快取
    }
    @Override
    protected void onPostExecute(Bitmap bitmap) {
        if (bitmap != null) view.setImageBitmap(bitmap);
    }
}

結論:佈局屬性決定 Measure 行為,Measure 行為直接驅動 getView 調用頻率。優先固定容器尺寸,輔以 ViewHolder 與異步載圖,即可徹底解決重複調用與效能問題。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved