現象
輸入無效搜索內容(如 `3/5/9#!¥`),列表閃現「北京市」後恢復正常,且非必現。
代碼疑點
- Filter 執行線程:`performFiltering` 運行在後台線程,`publishResults` 在 UI 線程。若 `filter()` 多次快速調用,舊結果可能在新結果後到達,導致 UI 閃現舊數據。
- 原始數據列表 `list` 被直接修改:`publishResults` 中 `list = (List) results.values;` 替換了引用,但 `getView` 可能仍持有舊列表引用,造成數據不一致。
- 拼音列表 `spylist` 未同步過濾:過濾邏輯中使用 `spylist.get(i)`,但 `spylist` 未隨 `list` 同步變化,導致索引錯位,匹配到錯誤項(如索引 0 的「北京市」)。
- 異步任務未取消:未在新過濾前取消舊任務,導致結果競態。
修復建議
- 在 `performFiltering` 開頭檢查 `Thread.interrupted()`,或用 `Filter` 子類覆寫 `cancel()` 取消舊任務。
- 過濾時同時構建新的 `newList` 和 `newSpyList`,保持索引一一對應,`publishResults` 時成對替換。
- 使用 `ArrayList` 而非 `List` 確保隨機訪問性能,避免 `remove` 導致 O(n²)。
- 調試時在 `performFiltering`/`publishResults` 打印線程 ID、列表大小、首項內容,定位競態時機。
優化方向
考慮用 `RecyclerView` + `ListAdapter` + `DiffUtil` 替代 `ListView` + `Filterable`,獲得更穩定的異步列表更新體驗。