RecyclerView搜索过滤器修改MutableList时崩溃问题求助
崩溃原因
你遇到的UnsupportedOperationException本质是:你的data变量虽然声明为MutableList<FishModel>,但实际引用的是一个不可变的List实现。比如当你从Room查询数据并直接赋值给data时,Room返回的List是不可修改的(底层是AbstractList的子类,默认不支持clear()、add()等修改操作),这时候调用data.clear()就会触发这个异常。
另外,你在publishResults里的类型转换也存在风险:results?.values as MutableList<FishModel>如果转换失败会抛出ClassCastException,而且没必要强制转成MutableList,addAll()本身就接受任意Collection类型。
分步修复方案
1. 确保data始终是真正的可变列表
修改data的setter方法,将传入的列表强制转换为可变列表,彻底避免不可变List的赋值问题:
var data = mutableListOf<FishModel>() set(value) { field = value.toMutableList() // 转成真正的MutableList,保证支持所有修改操作 dataFull = field.toList() // 同步更新原始数据副本,确保过滤始终基于完整数据集 notifyDataSetChanged() }
这样不管外部传入的是Room返回的不可变List,还是其他不可变列表,field都会是一个可自由修改的MutableList实例。
2. 安全处理Filter的结果
优化publishResults的代码,避免不安全的类型转换,同时简化修改逻辑:
override fun publishResults(constraint: CharSequence?, results: FilterResults?) { // 安全转换结果,默认返回空列表避免空指针异常 val filteredList = results?.values as? List<FishModel> ?: emptyList() // 直接利用setter方法,自动触发notifyDataSetChanged,无需手动调用 data = filteredList }
如果你更倾向于手动修改现有列表(避免创建新列表实例),也可以这样写:
override fun publishResults(constraint: CharSequence?, results: FilterResults?) { val filteredList = results?.values as? List<FishModel> ?: emptyList() data.clear() data.addAll(filteredList) notifyDataSetChanged() }
经过第一步的修复,data现在是真正的可变列表,clear()和addAll()不会再抛出异常。
3. 修复Room协程问题
之前的异常会导致主线程崩溃,进而中断未执行的协程。当你修复上述列表修改的问题后,主线程不再崩溃,Room的协程应该就能正常启动执行了。
额外注意事项
dataFull应该始终保存原始数据集的不可变副本,避免后续修改data影响过滤的数据源。上面的setter里已经处理了这一点:dataFull = field.toList(),toList()会返回一个不可变的List。- 永远不要直接将Room查询返回的List赋值给
MutableList变量,一定要通过toMutableList()转换为可修改的列表。
内容的提问来源于stack exchange,提问作者Lyam.D

