ListView 的 item 由動態添加的 LinearLayout 組成,循環創建 TextView 並設置文本。為容器設置 OnClickListener 時,點擊任意項彈出的 Toast 總是顯示**最後一項**的數據。
for (CarModel cm : carLists) {
String typeSeries = cm.getTypeSeries(); // 循環變量
String typeName = cm.getTypeName();
// ... 創建 View ...
holder.layout_carInfo.setOnClickListener(v ->
Toast.makeText(mActivity, typeSeries + typeName, ...).show()
);
}
Java 匿名內部類/Lambda 捕獲的是**變量引用**,而非當前值。循環結束後,typeSeries、typeName 保留最後一次賦值,所有 Listener 共享同一引用,故點擊時均顯示最後數據。
for (CarModel cm : carLists) {
final String series = cm.getTypeSeries(); // final 複本
final String name = cm.getTypeName();
// ...
holder.layout_carInfo.setOnClickListener(v ->
Toast.makeText(mActivity, series + name, ...).show()
);
}
for (CarModel cm : carLists) {
LinearLayout layout = new LinearLayout(mActivity);
// ... 添加 TextView ...
layout.setTag(cm); // 綁定整個數據對象
layout.setOnClickListener(v -> {
CarModel model = (CarModel) v.getTag();
Toast.makeText(mActivity, model.getTypeSeries() + model.getTypeName(), ...).show();
});
holder.layout_carInfo.addView(layout);
}
放棄 ListView + 動態 addView,改用 RecyclerView.Adapter,在 onBindViewHolder 中綁定數據與點擊事件,天然避免閉包問題,性能更優。
動態創建 View 綁定點擊時,切勿直接捕獲循環變量。用 final 複本、setTag 綁定數據對象,或升級到 RecyclerView 徹底解決。