I am trying to implement a fairly basic logic within my recyclerview adapter but notifyDataSetChanged()
is giving me quite the headache.
I have a filter method that looks like this:
fun filter(category: Int) {
Thread(Runnable {
activeFiltered!!.clear()
if (category == -1) {
filterAll()
} else {
filterCategory(category)
}
(mContext as Activity).runOnUiThread {
notifyDataSetChanged()
}
}).start()
}
where filterAll()
and filterCategory()
functions are quite easy:
private fun filterAll() {
activeFiltered?.addAll(tempList!!)
}
private fun filterCategory(category: Int) {
for (sub in tempList!!) {
if (sub.category == category) {
activeFiltered?.add(sub)
}
}
}
When I run this code and filter the list by category the activeFiltered list is updated correctly and contains the items I expect, but when notifyDataSetChanged()
is run it only cuts the list's range without updating the items.
Is there a way to fix this?
I also tried, instead of notifyDataSetChanged() to use:
activeFiltered!!.forEachIndexed {index, _ -> notifyItemChanged(index)}
but the problem is still there.
It isn't a threading issue either since I tried putting the whole logic in the main thread and the list still wasn't updated correctly.
This is my onBindViewHolder()
:
override fun onBindViewHolder(viewHolder: ActiveViewHolder, pos: Int) {
sub = activeFiltered!![pos]
inflateView()
}
This is where I inflate my text, sub is the instance variable set in the onBindViewHolder()
:
private fun inflateView() {
viewHolder.title.text = sub.title
}
It seems the implementation of onBindViewHolder()
is incorrect. In order to update a list item, the passed in viewHolder
parameter should be used (not the viewHolder
you created in the onCreateViewHolder()
).
The correct implementation should be like
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
}
By the way, it is not a good practice to hold something as a member field in order to access it in several methods. Feel free to pass it as arguments to such methods. In the above code I passed the sub
as argument and not stored it as a member.
And also it is not necessary to hold the viewHolder
that you create in onCreateViewHolder()
. We mostly need them in some callback methods (like onBindViewHolder()
, etc) and these methods will receive the right viewHolder
as arguments.