RecyclerView过滤器异常排查:删除搜索内容后列表未恢复原数据
过滤器逻辑错误分析与修复方案
核心问题
过滤器清空搜索内容后无法恢复原始列表,根源是没有保留完整的原始数据源,且过滤操作直接覆盖了适配器的数据源,导致清空时只能拿到已过滤后的子集。
具体逻辑漏洞
- 适配器的
transactions属性通过getGroup(1)获取值,但每次过滤后调用submitGroup(1, transactionsFiltered, true)会直接修改分组1的数据源。后续transactionsgetter返回的是过滤后的列表,而非初始的完整数据。 - 在
performFiltering中,当搜索内容为空时,你试图用transactions(此时已是过滤后的数据)恢复列表,自然无法回到初始状态。 - 初始化
transactionsFiltered时仅用了构造函数传入的初始transactions,但后续外部更新transactions时,没有同步更新这个基准数据源。
修复方案
1. 保存原始完整数据源
在适配器中新增一个变量存储初始的完整交易列表,作为过滤操作的基准:
class TransactionsAdapter( // ... 其他构造参数 transactions: List<Transaction> = emptyList(), // ... ) : DynamicListAdapter<...>(...) { // 保存原始完整数据源,避免外部修改影响 private var originalTransactions: List<Transaction> = transactions.toList() var transactions: List<Transaction> get() = getGroup(1) set(value) { submitGroup(1, value, true) // 外部更新数据源时同步更新原始基准 originalTransactions = value.toList() } // 初始化过滤列表为原始数据源 private var transactionsFiltered: List<Transaction> = originalTransactions // ... 其他代码 }
2. 修改过滤逻辑,基于原始数据源操作
更新Filter的performFiltering方法,清空搜索时直接使用原始数据源恢复:
override fun getFilter(): Filter = object : Filter() { override fun performFiltering(constraint: CharSequence?): FilterResults { val charString = constraint?.toString() ?: "" transactionsFiltered = if (charString.isEmpty()) { // 清空搜索时用原始完整数据源 originalTransactions } else { originalTransactions.filter { it.name.contains(charString, true) || it.value.toString().contains(charString) } } return FilterResults().apply { values = transactionsFiltered } } override fun publishResults(constraint: CharSequence?, results: FilterResults?) { transactionsFiltered = results?.values as? List<Transaction> ?: emptyList() submitGroup(1, transactionsFiltered, true) notifyDataSetChanged() } }
额外优化
- 移除
performFiltering中多余的ArrayList转换,直接使用filter返回的列表即可,简化代码。 - 确保
originalTransactions始终是不可变的副本(用toList()),避免外部修改原始列表导致基准数据异常。
内容的提问来源于stack exchange,提问作者Anderson Matos
相关产品推荐
相关产品推荐

