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

Android ListView 自定義圖片適配器實現:ViewHolder 模式與異步加載最佳實踐

     編輯:程式設計綜合問答

需求:ListView 顯示 10 項,每項包含標題文本 + 左側圖片 + 背景圖。自定義 Adapter 實現高性能渲染。

核心模式:ViewHolder + View 復用

public class LayoutListAdapter extends BaseAdapter {
    private Context context;
    private List items;
    private LayoutInflater inflater;

    public LayoutListAdapter(Context context, List items) {
        this.context = context;
        this.items = items;
        this.inflater = LayoutInflater.from(context);
    }

    @Override public int getCount() { return items.size(); }
    @Override public Object getItem(int pos) { return items.get(pos); }
    @Override public long getItemId(int pos) { return pos; }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder;
        if (convertView == null) {
            convertView = inflater.inflate(R.layout.layout1, parent, false);
            holder = new ViewHolder();
            holder.titleText = convertView.findViewById(R.id.addtext);
            holder.leftImage = convertView.findViewById(R.id.layoutframe);
            holder.background = convertView.findViewById(R.id.background_image); // 假設有
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }

        LayoutAdapterObj obj = items.get(position);
        holder.titleText.setText(obj.addString);
        
        // 關鍵:設置圖片資源(而非傳遞 ImageView 對象)
        holder.leftImage.setImageResource(getResId(obj.leftImageName)); // 需映射
        if (!TextUtils.isEmpty(obj.backgroundImageName)) {
            holder.background.setImageResource(getResId(obj.backgroundImageName));
        }
        return convertView;
    }

    static class ViewHolder {
        TextView titleText;
        ImageView leftImage;
        ImageView background;
    }

    private int getResId(String name) {
        // 將 "R.drawable.frame1" 字符串映射為實際 Res ID
        return context.getResources().getIdentifier(name.replace("R.drawable.", ""), "drawable", context.getPackageName());
    }
}

數據模型修正

public class LayoutAdapterObj {
    public String addString;        // 標題文本
    public String leftImageName;    // "frame1" (不含 R.drawable.)
    public String backgroundImageName; // "layout" 或具體名
    
    public LayoutAdapterObj(String addString, String leftImageName, String backgroundImageName) {
        this.addString = addString;
        this.leftImageName = leftImageName;
        this.backgroundImageName = backgroundImageName;
    }
}

// 構建數據
List list = new ArrayList<>();
list.add(new LayoutAdapterObj("1", "frame1", "layout"));
list.add(new LayoutAdapterObj("2", "frame2", "layout"));
// ...

關鍵錯誤修正

  • 不可傳遞 ImageView 實例:原代碼 `new ImageView(null, null, R.drawable.frame1)` 錯誤,View 需附著於 Window/Context,且不應在模型中持有 View 引用。
  • 模型持有資源標識符:字符串名稱或 Res ID,Adapter 中統一 `setImageResource()`。
  • ViewHolder 緩存 findViewById,避免重複查找。

異步加載圖片(網絡圖)擴展

// 在 getView 中
Glide.with(context).load(obj.imageUrl).placeholder(R.drawable.ph).into(holder.leftImage);
// 或自定義 ImageAsyncLoader

總結

模型存資源標識,Adapter 负責渲染,ViewHolder 加速復用,異步庫處理網絡圖——構建高性能 ListView 圖文列表。

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