我有一个奇怪的问题与notifyDataSetChanged()在我的回收适配器。如果我在数组中保留5个项目的代码工作良好,我可以检查复选框在项目我LongClick,但当我添加5个项目或更多的数组其他复选框被选中在我的列表。
我使用一个布尔值切换可见和GONE之间的复选框,当用户LongClicks以及。
下面是我的代码:class RecyclerAdapter(private val listActivity: ListActivity) : RecyclerView.Adapter<RecyclerAdapter.Holder>() {
lateinit var binding: ActivityListItemRowBinding
var checkboxesVisibility = false
val dummyArrayWorks = arrayOf("000", "111", "222", "333", "444")
val dummyArrayFails = arrayOf("000", "111", "222", "333", "444", "555")
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Holder {
binding = ActivityListItemRowBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return Holder(binding)
}
override fun getItemCount(): Int = dummyArrayFails.size
@SuppressLint("NotifyDataSetChanged")
override fun onBindViewHolder(holder: Holder, position: Int) {
val item = dummyArrayFails[position]
holder.binding.checkbox.visibility = if (checkboxesVisibility) VISIBLE else GONE
holder.bindItem(item)
holder.itemView.setOnLongClickListener {
if (!checkboxesVisibility) {
checkboxesVisibility = true
holder.binding.checkbox.isChecked = true
notifyDataSetChanged()
true
} else {
false
}
}
holder.itemView.setOnClickListener {
if (!checkboxesVisibility) {
//Some other unrelated code
} else {
holder.binding.checkbox.isChecked = !holder.binding.checkbox.isChecked
notifyDataSetChanged()
}
}
}
class Holder(internal val binding: ActivityListItemRowBinding) : RecyclerView.ViewHolder(binding.root) {
var item = String()
fun bindItem(item: String) {
this.item = item
binding.itemPlaceHolder.text = item
}
}
}
我应该补充的是,当我删除复选框的开关时,只是在第一次加载时显示复选框,点击匹配复选标记没有问题。
有人知道发生了什么事吗?所有的帮助将非常感激!
问题是你在ViewHolder
本身中保持复选状态-你正在根据单击打开和关闭其复选框,对吗?
RecyclerView
的工作方式是,而不是有一个ViewHolder
为每一个单独的项目(像一个ListView
做),它只创建一个少数的-足以在屏幕上和更多的滚动-和回收那些,使用它们来显示不同的项目。
这就是onBindViewHolder
的作用——当它需要显示position
的项目时,它会从它的池中给你一个ViewHolder
,并说给你,用它来显示这个项目的详细信息。在这里,你可以设置文本、更改图像,以及设置复选框状态等内容,以反映特定的项目。
你所做的是你没有将项目的状态存储在任何地方,你只是在视图holder上设置了复选框。如果你选中它,每个在可重用容器对象中显示的物品都会被选中。这就是为什么你会看到它在其他项目上弹出的原因——checked状态与项目本身无关,只是它们碰巧使用了哪个视图holder,因为它们在列表中的位置。
因此,您需要将它们的checked状态保存在某个地方—它可以像匹配项目列表长度的布尔数组一样简单。然后在绑定数据(显示数据)时设置并从中获取。利用现有资源:
// all default to false
val itemChecked = BooleanArray(items.size)
override fun onBindViewHolder(holder: Holder, position: Int) {
...
// when displaying the data, refer to the checked state we're holding
holder.binding.checkbox.checked = itemChecked[position]
...
holder.itemView.setOnLongClickListener {
...
// when checking the box, update our checked state
// since we're calling notifyDataSetChanged, the item will be redisplayed
// and onBindViewHolder will be called again (which sets the checkbox)
itemChecked[position] = true
// notifyItemChanged(position) is better here btw, just refreshes this one
notifyDataSetChanged()
...
}
}