我试图在我的recyclerview适配器中实现一个相当基本的逻辑,但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
}
似乎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
作为参数。
我认为你在onBindView()
中使用原始数组而不是过滤后的数组。