動態建立多個 GridView 並在同一個 Activity 中顯示時,若直接使用成員變數 gridView 於 OnItemClickListener 內取值,會發生「點擊任一 GridView 都取到最後一個的資料」或「下標越界」的經典 Bug。
// 成員變數
GridView gridView;
// 迴圈建立多個 GridView
for (...) {
gridView = new MyGridView(...);
gridView.setAdapter(sAdapter);
gridView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int pos, long id) {
// ❌ 這裡用的是外部成員變數 gridView,迴圈結束時指向最後一個實例
HashMap<String,String> map = (HashMap) gridView.getItemAtPosition(pos);
...
}
});
}
迴圈結束後,gridView 指向最後一個實例,所有 Listener 共用同一個引用。
class MyOnItemClickListener implements AdapterView.OnItemClickListener {
private final GridView gv;
public MyOnItemClickListener(GridView gv) { this.gv = gv; }
@Override
public void onItemClick(AdapterView<?> parent, View view, int pos, long id) {
HashMap<String,String> map = (HashMap) gv.getItemAtPosition(pos); // ✅ 使用捕獲的實例
String btnText = map.get("fenlei_btnlist_btn_text");
// 後續跳轉邏輯...
}
}
// 使用時
gridView.setOnItemClickListener(new MyOnItemClickListener(gridView));
// 使用 final 或 effectively final 區域變數
final GridView currentGridView = gridView; // 迴圈內部區域變數
gridView.setOnItemClickListener((parent, view, pos, id) -> {
HashMap<String,String> map = (HashMap) currentGridView.getItemAtPosition(pos);
...
});
final 變數或建構子傳遞,明確捕獲語意。RecyclerView + ViewHolder 模式替代 GridView,效能與記憶體表現更優。