ListView的`convertView`復用機制導致**無法直接遍歷所有Item View獲取數據**(非可見項View不存在/被復用)。正確做法是實時同步數據到模型層(數據源集合),最後遍歷數據源。本文詳解HashMap輔助方案與最佳實踐。
❌ 嘗試 `for (int i=0; i正確架構:數據驅動視圖
// 1. 數據模型類 class TempRecord { String time; String temperature; boolean isValid; } // 2. 數據源列表(單一真實來源) ListdataList = new ArrayList<>(); // 3. Adapter中實時同步 public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder; if (convertView == null) { holder = new ViewHolder(); convertView = inflater.inflate(R.layout.item_temp, parent, false); holder.timeTv = convertView.findViewById(R.id.time); holder.tempEt = convertView.findViewById(R.id.temperature); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } final TempRecord record = dataList.get(position); holder.timeTv.setText(record.time); holder.tempEt.setText(record.temperature); // 4. 關鍵:輸入框實時監聽,直接更新模型 holder.tempEt.addTextChangedListener(new TextWatcher() { @Override public void afterTextChanged(Editable s) { record.temperature = s.toString(); // 即時寫回數據源 } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {} @Override public void onTextChanged(CharSequence s, int start, int before, int count) {} }); // 時間選擇器同理更新 record.time return convertView; } 輔助方案:HashMap暫存(適用於不想改模型類)
// 全局/Activity級 MaptempInputs = new HashMap<>(); // Map timeInputs = new HashMap<>(); // 在 getView 中: holder.tempEt.addTextChangedListener(new TextWatcher() { @Override public void afterTextChanged(Editable s) { tempInputs.put(position, s.toString()); // 實時存 } // ... }); // 最後保存時遍歷 Map: for (int i = 0; i < dataList.size(); i++) { String temp = tempInputs.get(i); String time = timeInputs.get(i); // 組裝保存 } 關鍵最佳實踐
- 拒絕遍歷View樹:ListView/RecyclerView核心機制決定了View非持久化。
- 單一數據源原則:所有用戶輸入即時寫入模型/Map,UI只是數據的投影。
- 去抖動優化:頻繁輸入場景(如搜索框)用`Debounce`/RxJava `debounce`減少寫入頻率。
- 輸入驗證:保存前遍歷數據源檢查完整性/合法性。
- 遷移RecyclerView**:`RecyclerView.ViewHolder` + `ListAdapter` + `DiffUtil` 更現代、高效、穩健。
場景總結
場景 推薦方案 少量固定項(<10)、無復用 LinearLayout + 手動addView,可直接遍歷子View 列表、動態項、需復用 ListView/RecyclerView + **模型實時同步** 複雜表單、多類型項 RecyclerView + 多ItemType + 數據綁定庫 鐵律:數據變,UI跟著變;UI變,數據要先變。別想著去問View要數據,View只負責顯示。