Próbuję dodać wyszukiwanie do filtrowania w RecyclerView. ale aplikacja ulega awarii z następującym błędem:

Kotlin.TypeCastException: nie można rzutować wartości null na typ niezerowy kotlin.collections.List at com.kabelash.movies.ui.PostListAdapter $ searchFilter $ 1.publishResults (PostListAdapter.kt: 87) w android.widget.Filter $ ResultsHandler.handleMessage (Filter.java:284) na android.os.Handler.dispatchMessage (Handler.java:107) na android.os.Looper.loop (Looper.java:214)

Adapter:

class PostListAdapter: RecyclerView.Adapter<PostListAdapter.ViewHolder>(), Filterable {
    private lateinit var postListFiltered:List<Data>
    private lateinit var postListFull:List<Data>

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val binding: ListItemBinding = DataBindingUtil.inflate(LayoutInflater.from(parent.context), R.layout.list_item, parent, false)
        return ViewHolder(binding)
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        holder.bind(postListFiltered[position])
    }

    override fun getItemCount(): Int {
        return if(::postListFiltered.isInitialized) postListFiltered.size else 0
    }

    fun updatePostList(postList:List<Data>){
        this.postListFiltered = postList
        notifyDataSetChanged()
    }

    class ViewHolder(private val binding: ListItemBinding): RecyclerView.ViewHolder(binding.root){
        private val viewModel = MoviesViewModel()

        fun bind(post:Data){
            viewModel.bind(post)
            binding.viewModel = viewModel
        }

    }

    override fun getFilter(): Filter? {
        return searchFilter
    }

    private val searchFilter: Filter = object : Filter() {
        override fun performFiltering(constraint: CharSequence?): FilterResults? {
            val filteredList: MutableList<Data> = ArrayList()
            if (constraint == null || constraint.isEmpty()) {
                filteredList.addAll(postListFull)
            } else {
                val filterPattern = constraint.toString().toLowerCase().trim()
                for (item in postListFull) {
                    if (item.title.toLowerCase().contains(filterPattern) || item.genre.toLowerCase().contains(filterPattern)) {
                        filteredList.add(item)
                    }
                }

            }
            val results = FilterResults()
            results.values = filteredList
            return results
        }

        override fun publishResults(constraint: CharSequence?,results: FilterResults) {
            postListFiltered = (results.values as List<Data>)
            notifyDataSetChanged()
        }
    }
}

Jeśli potrzebujesz innego pliku klasowego, daj mi znać. Czy ktoś może mi pomóc w rozwiązaniu tego?

2
GK007 16 grudzień 2019, 18:42
Wygląda na to, że result.values ​​ma wartość null w postListFiltered = (results.values as List<Data>) — to jest przyczyna awarii. postListFiltered nie dopuszcza wartości null.
 – 
ror
16 grudzień 2019, 18:51
 – 
a_local_nobody
16 grudzień 2019, 19:04
3
Żadna z dotychczasowych odpowiedzi nie wyjaśnia, w jaki sposób results.values może mieć wartość zerową. Implementacja filtru bardzo wyraźnie zawsze przypisuje mu wartość nie dopuszczającą wartości null. Powinieneś być w stanie uniknąć natychmiastowego błędu z postListFiltered = (results.values as List<Data>?).orEmpty(), ale prawdopodobnie maskuje to inny błąd, który nadal będziesz musiał rozwiązać.
 – 
Tenfour04
16 grudzień 2019, 19:05
Czy Twój dziennik zawiera ostrzeżenie z tagiem „Filter” i komunikat „Wystąpił wyjątek podczas wykonywaniaFiltrowanie()!” ?
 – 
Nitrodon
16 grudzień 2019, 19:09
1
PostListFiltered = (results.values ​​as List?).orEmpty() jest w rzeczywistości odpowiedzią!
 – 
Gueorgui Obregon
17 grudzień 2019, 16:18

3 odpowiedzi

Przed wykonaniem rzutowania będziesz musiał wykonać sprawdzenie zerowe, zmodyfikuj metodę pulishResults w następujący sposób.

   override fun publishResults(constraint: CharSequence?,results: FilterResults) {
                postListFiltered = if(results == null || results.values == null)
                                       ArrayList<Data>() 
                                   else
                                        results.values
                notifyDataSetChanged()
            }
0
mightyWOZ 16 grudzień 2019, 18:54

To jest ta linia: results.values as List<Data>

results.values jest zerowa, a ty mówisz, że ma to być lista niezerowa, czego nie może zrobić.

1
TomH 16 grudzień 2019, 18:56

Jak słusznie wskazują pozostałe dwie odpowiedzi, Twoje results.values jest zerowe. Ale kod wyraźnie pokazuje, że FilterResults zwrócone z performFiltering zawsze ma pole values niezerowe. Jak to się mogło stać?

Krótkie spojrzenie na kod źródłowy Filter daje możliwą odpowiedź:

// Filter.RequestHandler.handleMessage(Message msg)

try {
    args.results = performFiltering(args.constraint);
} catch (Exception e) {
    args.results = new FilterResults();
    Log.w(LOG_TAG, "An exception occured during performFiltering()!", e);
}

Mówiąc prostym językiem, jeśli performFiltering() zgłasza wyjątek, filtr przechwytuje wyjątek i używa pustego elementu FilterResults zamiast tego, co w innym przypadku zostałoby zwrócone. Ślad stosu dla tego wyjątku można znaleźć w logcat.

Patrząc na twoją funkcję performFiltering, jedynym wyjątkiem, który się wyróżnia, jest UninitializedPropertyAccessException. Jeśli okaże się, że jest to zgłoszony wyjątek, możesz to naprawić, sprawdzając, czy właściwość fullPostList jest zainicjowana, lub jawnie inicjując ją na pustej liście.

0
Nitrodon 16 grudzień 2019, 19:41