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

如何在Filterable Adapter中避免使用notifyDataSetChanged?

过滤场景下替换notifyDataSetChanged的实现方案

Android Studio抛出该警告的原因是notifyDataSetChanged()会触发RecyclerView全量重绘所有可见条目、清空所有item缓存,没有过渡动画,在列表数据量大的情况下性能损耗十分明显,官方推荐优先使用更精准的局部更新通知。

在搜索过滤这种需要整体替换列表数据集的场景下,最优方案是使用DiffUtil自动计算新旧过滤列表的差异,自动生成对应插入、删除、更新的局部通知,完全替代notifyDataSetChanged(),同时还自带列表切换动画,体验更好。

修改步骤

1. 调整Filter逻辑,在异步线程计算列表差异

Filter的performFiltering方法本身运行在工作线程,我们可以把计算Diff的耗时操作放在这里执行,避免阻塞主线程:

override fun getFilter() = object : Filter() {

    override fun performFiltering(constraint: CharSequence): FilterResults {
        val newFilterList = if (constraint.length < 2) {
            coins
        } else {
            val pattern = constraint.toString().lowercase().trim()
            coins.filter { it.name.lowercase().contains(pattern) }
        }

        // 工作线程计算新旧列表的差异,不卡UI
        val diffResult = DiffUtil.calculateDiff(object : DiffUtil.Callback() {
            override fun getOldListSize(): Int = filter.size
            override fun getNewListSize(): Int = newFilterList.size

            override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
                // 此处用Coin的唯一标识判断是否为同一个条目,没有唯一id可以用name+image等组合字段
                return filter[oldItemPosition].id == newFilterList[newItemPosition].id
            }

            override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
                // 判断条目内容是否完全相同,若Coin为Kotlin data类可直接用==判断所有属性
                return filter[oldItemPosition] == newFilterList[newItemPosition]
            }
        })

        return fetchResults(Pair(newFilterList, diffResult))
    }

    private fun fetchResults(data: Pair<List<Coin>, DiffUtil.DiffResult>): FilterResults {
        val results = FilterResults()
        results.values = data
        return results
    }

    override fun publishResults(constraint: CharSequence, results: FilterResults) {
        val (newFilterList, diffResult) = results.values as Pair<List<Coin>, DiffUtil.DiffResult>
        // 更新数据集
        filter.clear()
        filter.addAll(newFilterList)
        // 提交差异,自动触发对应局部更新通知
        diffResult.dispatchUpdatesTo(this@CoinsAdapter)
    }
}

2. 可选优化(推荐)

如果你的Coin类还不是Kotlin数据类,建议改为data class,无需手写属性对比逻辑,==会自动判断所有字段是否相等,areContentsTheSame的逻辑可以直接复用。

修改完成后即可完全消除AS警告,过滤操作的性能和动画体验都会有明显提升。


内容的提问来源于stack exchange,提问作者Ravers

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 20:54:00