Kotlin实现的RecyclerView适配器Filter过滤功能失效如何解决
问题根因
- 集合引用共用:Kotlin集合默认是引用传递,你在init块中直接将
dataSet、dataSetFiltered赋值为传入的dataSetIn引用,三个变量指向同一个内存地址的集合,任意修改都会联动影响另外两个,导致过滤逻辑完全混乱。 - 线程安全违规:
performFiltering方法运行在独立工作线程,你直接在该方法内修改UI层渲染用的全局变量dataSetFiltered,存在并发冲突风险,且该操作完全多余——最终过滤结果会通过publishResults回调回主线程再赋值。 - 空搜索逻辑错误:搜索内容为空时你直接调用
dataSetFiltered.addAll(dataSet),没有先清空原有过滤数据,会导致数据重复累加。 - 缺少数项计数方法:你贴出的代码中没有重写
getItemCount方法返回dataSetFiltered.size,会导致RecyclerView无法正常渲染数据。 - 语法错误:
onBindViewHolder方法中括号位置错误,导致setAnimation方法调用不在方法体内,编译阶段就会报错。
修复后完整代码
class ClothingListAdapterKt( private val dataSetIn: MutableList<Clothing>, private val listener: ClothingListAdapterKt.OnItemClickListener, private val context: Context ) : RecyclerView.Adapter<ClothingListAdapterKt.ViewHolder>(), Filterable { private var lastPosition = -1 // 初始化直接做集合拷贝,避免共用引用,无需额外init块赋值 var dataSet = dataSetIn.toMutableList() var dataSetFiltered = dataSetIn.toMutableList() override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { // 替换为你自己的item布局与ViewHolder创建逻辑即可 val view = LayoutInflater.from(context).inflate(R.layout.your_clothing_item_layout, parent, false) return ViewHolder(view) } override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) { val currentClothing: Clothing = dataSetFiltered[position] // 保留你自己的视图属性赋值逻辑 setAnimation(viewHolder.itemView, position) } // 必须重写该方法返回过滤后数据集长度 override fun getItemCount(): Int = dataSetFiltered.size override fun getFilter(): Filter { return object : Filter() { override fun performFiltering(constraint: CharSequence?): FilterResults { val charString = constraint.toString().trim() // 所有过滤操作使用局部变量,不要修改全局数据集避免线程冲突 val filteredList = if (charString.isEmpty()) { // 空搜索直接返回原始数据集的拷贝 dataSet.toMutableList() } else { dataSet.filter { it.name.lowercase().contains(charString.lowercase()) }.toMutableList() } return FilterResults().apply { values = filteredList count = filteredList.size } } override fun publishResults(constraint: CharSequence?, results: FilterResults?) { results?.values?.let { dataSetFiltered = it as MutableList<Clothing> notifyDataSetChanged() } } } } // 保留你原有ViewHolder定义、动画逻辑、点击事件接口即可 inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) private fun setAnimation(itemView: View, position: Int) { // 你的原有动画实现 } interface OnItemClickListener { // 你的原有点击事件定义 } }
配套调用注意点
如果后续需要更新适配器的原始数据集,不要直接修改外部传入的clothing集合,要修改适配器内部的dataSet变量,修改后调用对应刷新方法再触发过滤即可生效。
内容的提问来源于stack exchange,提问作者BlazeCodeDev
相关产品推荐
相关产品推荐

