ListView (視圖)
│
▼ setAdapter()
BaseAdapter (橋樑) ◄── 資料源
│
├── getCount() → 多少行
├── getItem(position) → 某行資料
├── getItemId(position) → 唯一 ID (穩定 ID 啟用優化)
└── getView(position, convertView, parent) → 核心:行視圖創建/復用
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;
}
}
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 或自行實現動畫
}
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**: