迁移到 AndroidX 后,RecyclerView 可过滤的 performFiltering() 不起作用

Posted

技术标签:

【中文标题】迁移到 AndroidX 后,RecyclerView 可过滤的 performFiltering() 不起作用【英文标题】:RecyclerView filterable performFiltering() not working after migrating to AndroidX 【发布时间】:2019-05-08 19:01:01 【问题描述】:

在迁移到 androidX 后,我注意到我的搜索功能不再工作了。我在这里查看过官方文档https://developer.android.com/reference/android/widget/Filterable,但没有任何线索。

这是我的 RecyclerView 适配器 ListProdukAdapter.kt,它实现了 Filterable:

class ListProdukAdapter(private val context: Context, private val data: List<Produk>, private val act: MainActivity, private val kategori: String) : RecyclerView.Adapter<ListProdukAdapter.SampleViewHolders>(), Filterable 
    private var dataFiltered: List<Produk>? = null
    private val h: Helper
    private val a: HelperAplikasi

    init 
        this.dataFiltered = data
        this.h = act.h
        this.a = act.a
    

    ...

    override fun getFilter(): Filter 
        return object : Filter() 
            override fun performFiltering(charSequence: CharSequence): Filter.FilterResults 
                val keyword = charSequence.toString().toLowerCase()
                dataFiltered = if (keyword.isEmpty()) 
                    data
                 else 
                    val filteredList = ArrayList<Produk>()
                    var kategoriBf = ""
                    var kategoriHit = 0
                    val kategoriNum = HashMap<String, Int>()
                    for (res in data) 
                        if (!h.cekVal(res.judul) || h.cekFilter(keyword, res.judul, res.kategorI_LENGKAP, res.keywords) > 0) 
                            filteredList.add(res)
                            if (h.cekVal(res.judul)) 
                                if (kategoriBf != res.kategori && !kategoriBf.isEmpty()) 
                                    kategoriNum[kategoriBf] = kategoriHit
                                    kategoriHit = 0
                                
                                kategoriHit++
                                kategoriBf = res.kategori
                            
                        
                    
                    kategoriNum[kategoriBf] = kategoriHit
                    Log.e("kategori_num", kategoriNum.toString())
                    Log.e("kategori_num_item_bf", filteredList.size.toString() + "")
                    for (etl in filteredList) 
                        if (!h.cekVal(etl.judul)) 
                            val jumlah = kategoriNum[etl.kategori]
                            if (jumlah == null || jumlah < 1)
                                etl.stok = 0
                            else
                                etl.stok = jumlah
                        
                    
                    Log.e("kategori_num_item_af", filteredList.size.toString() + "")
                    filteredList
                
                val filterResults = Filter.FilterResults()
                filterResults.values = dataFiltered ?: ArrayList<Produk>()
                return filterResults
            

            override fun publishResults(charSequence: CharSequence, filterResults: Filter.FilterResults) 
                @Suppress("UNCHECKED_CAST")
                dataFiltered = filterResults.values as ArrayList<Produk>
                notifyDataSetChanged()
            
        
    

    ...


请注意,在我迁移到 AndroidX 之前,它就像一个魅力。我的h.cekFilter() 方法只是我的自定义助手,用于检查字符串是否包含关键字,没有问题。现在,每当我在搜索输入中输入任何内容时都会发生崩溃:

kotlin.TypeCastException: null cannot be cast to non-null type kotlin.collections.ArrayList<com.jukat.jualdekat.objects.Produk> /* = java.util.ArrayList<com.jukat.jualdekat.objects.Produk> */
        at com.jukat.jualdekat.adapters.ListProdukAdapter$getFilter$1.publishResults(ListProdukAdapter.kt:239)
        at android.widget.Filter$ResultsHandler.handleMessage(Filter.java:282)
        at android.os.Handler.dispatchMessage(Handler.java:111)
        at android.os.Looper.loop(Looper.java:207)
        at android.app.ActivityThread.main(ActivityThread.java:5692)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:908)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:769)

当我尝试将(第 239 行)从 dataFiltered = filterResults.values as ArrayList&lt;Produk&gt; 更改为 dataFiltered = filterResults.values as ArrayList&lt;Produk&gt;? 时,即使我键入了 1 个明显包含在数据中的字母,结果也是零。是的,我在使用类似实现的所有其他活动中遇到了同样的错误。请帮忙。

【问题讨论】:

您是通过更改依赖项还是通过 IntelliJ 手动迁移的? @nimi0112 通过 Android Studio 3.2 中的重构菜单 @pskink 我不知道。你能给我一个例子或参考吗? @pskink no way :/ 这似乎是一个过时且臃肿的自定义适配器类。它使用内部类 ArrayFilter()Filter 扩展,这就像我的 getFilter() 不再工作了。 让我们continue this discussion in chat。 【参考方案1】:

对不起各位。我花了几个小时来解决这个问题,最终我发现它实际上是什么。显然这个问题根本与 AndroidX 无关,而是因为我在我的 Helper 类中的自定义方法,我碰巧在我迁移到 AndroidX 之前将它从 Java 转换为 Kotlin,这让我误会了。

performFiltering() 方法有一个可以为空的CharSequence 参数,所以我的h.cekFilter() 方法中应该有CharSequence?,如下所示。

fun cekFilter(keyword: CharSequence?, vararg teks: CharSequence?): Int 
    ...

另一个问题是 Logcat 在我的 Helper 类中没有显示任何错误迹象,而是我的 performFilter() 中途停止,然后将 null filterResults.values 传递给 publishResults(),然后在 Logcat 中触发异常。很奇怪。

【讨论】:

以上是关于迁移到 AndroidX 后,RecyclerView 可过滤的 performFiltering() 不起作用的主要内容,如果未能解决你的问题,请参考以下文章

迁移到 Androidx 后无法解析符号 R

迁移到 AndroidX 后,RecyclerView 可过滤的 performFiltering() 不起作用

无法解析 android.support.design。迁移到 AndroidX 后

在 Android Studio 中迁移到 AndroidX 后出现 YoutubeAndroidPlayerAPI 错误

Flutter 升级到 v1.14.7-pre.83 并迁移到 AndroidX 后只显示白屏

Androidx 迁移:NoClassDefFoundError