You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 05:09:02