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

Android ListView 資料填充完整指南:BaseAdapter 實現與 ViewHolder 優化

     編輯:程式設計綜合問答

核心組件關係

ListView (視圖)
    │
    ▼ setAdapter()
BaseAdapter (橋樑) ◄── 資料源
    │
    ├── getCount()          → 多少行
    ├── getItem(position)   → 某行資料
    ├── getItemId(position) → 唯一 ID (穩定 ID 啟用優化)
    └── getView(position, convertView, parent) → 核心:行視圖創建/復用

最小可行實現 (Java)


public class MyAdapter extends BaseAdapter {
    private Context context;
    private List data; // 資料源
    
    public MyAdapter(Context context, List data) {
        this.context = context;
        this.data = data;
    }
    
    @Override public int getCount() { return data.size(); }
    @Override public Object getItem(int pos) { return data.get(pos); }
    @Override public long getItemId(int pos) { return pos; } // 簡單場景用 position
    
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder;
        if (convertView == null) {
            convertView = LayoutInflater.from(context).inflate(R.layout.list_item, parent, false);
            holder = new ViewHolder();
            holder.textView = convertView.findViewById(R.id.tv_text);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }
        // 綁定資料
        holder.textView.setText(data.get(position));
        return convertView;
    }
    
    static class ViewHolder {
        TextView textView;
    }
}

Activity 中使用


ListView listView = findViewById(R.id.listView);
List data = new ArrayList<>();
for (int i=0; i<20; i++) data.add("Item " + i);
MyAdapter adapter = new MyAdapter(this, data);
listView.setAdapter(adapter);

進階:動態更新資料


// 在 Adapter 中添加
public void updateData(List newData) {
    this.data.clear();
    this.data.addAll(newData);
    notifyDataSetChanged(); // 通知 ListView 重繪
}

// 支援插入/刪除單項 (配合動畫)
public void addItem(int pos, String item) {
    data.add(pos, item);
    notifyItemInserted(pos); // 需繼承 RecyclerView.Adapter 或自行實現動畫
}

Kotlin 簡化版 (擴展函數)


class MyAdapter(private val data: List) : BaseAdapter() {
    override fun getCount() = data.size
    override fun getItem(pos: Int) = data[pos]
    override fun getItemId(pos: Int) = pos.toLong()
    
    override fun getView(pos: Int, convertView: View?, parent: ViewGroup): View {
        val view = convertView ?: LayoutInflater.from(parent.context).inflate(R.layout.list_item, parent, false)
        view.findViewById(R.id.tv_text).text = data[pos]
        return view
    }
}

常見坑點與優化

問題原因解決
項目顯示錯亂/重複未使用 ViewHolder 或 convertView 復用邏輯錯誤嚴格遵循 `if (convertView==null) create+tag else getTag` 模式
圖片加載閃爍/錯位異步加載圖片時項目被復用,舊請求回調更新了新項目給 ImageView 打標籤 `setTag(url)`,回調時比對 URL 一致才設置圖片
點擊事件無效行佈局 `android:descendantFocusability="blocksDescendants"` 缺失在根佈局添加該屬性,或按鈕設置 `focusable="false"`
大量資料卡頓ListView 仍在主執行緒測量佈局遷移至 RecyclerView (強制 ViewHolder、預載入、佈局管理器分離)

現代替代:RecyclerView

新專案**強烈建議直接使用 RecyclerView**:

  • 強制 ViewHolder 模式 (無 `convertView` 易錯邏輯)。
  • 支援 `LinearLayoutManager`/`GridLayoutManager`/`StaggeredGridLayoutManager` 靈活佈局。
  • 內建 `notifyItemInserted/Removed/Changed` 精細動畫。
  • `DiffUtil` 高效增量更新。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved