首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Android 自定義 ListView getView 空指針錯誤:ViewHolder 模式缺失分析

     編輯:程式設計綜合問答

錯誤現象

自定義 BaseAdapter 中 getView() 設置 TextView 文字時拋出 NullPointerException,日誌提示 findViewById(R.id.textView2) 返回 null。

代碼缺陷分析

// 原有問題代碼片段
@Override
public View getView(int arg0, View arg1, ViewGroup arg2) {
    View customView = arg1;
    ViewHolder holder;
    if (arg1 == null) {
        customView = inflater.inflate(R.layout.listrow, null); // 錯誤:未傳入 parent
        holder = new ViewHolder();
        holder.tv = (TextView) customView.findViewById(R.id.textView2);
        // 缺失:customView.setTag(holder);
    } else {
        holder = (ViewHolder) customView.getTag(); // 因未 setTag,此處取得 null
    }
    // ...
    holder.tv.setText("" + pinfo.appname); // NPE:holder 為 null
    return customView;
}

三大核心錯誤

  1. inflate 缺少 parent 參數:inflate(layout, null) 導致佈局參數失效,子視圖尺寸異常
  2. 缺失 setTag(holder):convertView 複用時無法取回 ViewHolder,導致重複 findViewById 或 holder 為 null
  3. ViewHolder 非 static:內部類持有外部類引用,增加記憶體壓力

標準修正版

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    ViewHolder holder;
    if (convertView == null) {
        // 正確:傳入 parent,attachToRoot=false
        convertView = inflater.inflate(R.layout.listrow, parent, false);
        holder = new ViewHolder();
        holder.iv = convertView.findViewById(R.id.imageView1);
        holder.tv = convertView.findViewById(R.id.textView2);
        holder.cb = convertView.findViewById(R.id.checkBox1);
        convertView.setTag(holder); // 關鍵:綁定 holder
    } else {
        holder = (ViewHolder) convertView.getTag();
    }

    PInfo pinfo = installedApps.get(position);
    holder.tv.setText(pinfo.appname);
    holder.iv.setImageDrawable(pinfo.icon);
    // CheckBox 狀態同步邏輯...
    return convertView;
}

static class ViewHolder { // static 避免記憶體洩漏
    ImageView iv;
    TextView tv;
    CheckBox cb;
}

進階優化建議

  • 使用 ViewBinding:編譯期生成綁定類,消除 findViewById 與型別轉換錯誤
  • DiffUtil + ListAdapter:遷移至 RecyclerView,自動計算差異動畫
  • 圖片載入庫:Glide/Picasso/Coil 異步載入圖標,避免主執行緒阻塞
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved