NotifyDataSetChanged не обновляет RecyclerView правильно - PullRequest
0 голосов
/ 28 августа 2018

Я пытаюсь реализовать довольно простую логику в моем адаптере для повторного просмотра, но notifyDataSetChanged() вызывает у меня головную боль.

У меня есть метод фильтра, который выглядит следующим образом:

fun filter(category: Int) {
    Thread(Runnable {
        activeFiltered!!.clear()

        if (category == -1) {
            filterAll()
        } else {
            filterCategory(category)
        }

        (mContext as Activity).runOnUiThread {
            notifyDataSetChanged()
        }
    }).start()
}

, где функции filterAll() и filterCategory() довольно просты:

private fun filterAll() {
    activeFiltered?.addAll(tempList!!)
}

private fun filterCategory(category: Int) {
    for (sub in tempList!!) {
        if (sub.category == category) {
            activeFiltered?.add(sub)
        }
    }
}

Когда я запускаю этот код и фильтрую список по категориям, список activeFiltered корректно обновляется и содержит ожидаемые элементы, но при запуске notifyDataSetChanged() он только сокращает диапазон списка без обновления элементов.

Есть ли способ это исправить?

Я также попытался вместо notifyDataSetChanged () использовать:

activeFiltered!!.forEachIndexed {index, _ ->  notifyItemChanged(index)}

но проблема все еще существует.

Это также не проблема с потоками, так как я пытался поместить всю логику в основной поток, и список все еще не обновлялся правильно.

Это мой onBindViewHolder():

override fun onBindViewHolder(viewHolder: ActiveViewHolder, pos: Int) {
    sub = activeFiltered!![pos]
    inflateView()

}

Здесь я раздуваю свой текст, sub - это переменная экземпляра, установленная в onBindViewHolder():

private fun inflateView() {
        viewHolder.title.text = sub.title
    }

Ответы [ 2 ]

0 голосов
/ 02 сентября 2018

Кажется, реализация onBindViewHolder() неверна. Для обновления элемента списка следует использовать переданный в viewHolder параметр (не тот viewHolder, который вы создали в onCreateViewHolder()).

Правильная реализация должна быть похожа на

override fun onBindViewHolder(viewHolder: ActiveViewHolder, pos: Int) {
    val sub = activeFiltered!![pos]
    inflateView(viewHolder, sub)
}

private fun inflateView(viewHolder: ActiveViewHolder, sub: <YourDataType>) {
    viewHolder.title.text = sub.title
}

Кстати, не рекомендуется хранить что-либо в качестве поля-члена, чтобы получить к нему доступ несколькими способами. Не стесняйтесь передавать это как аргументы таким методам. В приведенном выше коде я передал sub в качестве аргумента и не сохранил его как член.

А также нет необходимости держать viewHolder, который вы создаете в onCreateViewHolder(). Мы в основном нуждаемся в них в некоторых методах обратного вызова (например, onBindViewHolder() и т. Д.), И эти методы получат правильное значение viewHolder в качестве аргументов.

0 голосов
/ 01 сентября 2018

Я думаю, что вы используете исходный массив в onBindView() вместо отфильтрованного.

...