我有一个回收站视图,可以从数据库中获取详细信息。房间数据库给出了FriendEntity的ArrayList,它可以正常工作。我想首先为整个列表创建一个未选中的框图像,如果我点击该图像,它应该变成一个选中的框图像。但是,当我实现此目标时,当我单击recyclerView的第一个项目时,我的recyclerView的第16个项目从未选中更改为已选中,而第二个,第17个,第3个和第18个同样如此。我不知道这是否是Recycler View适配器或其他问题。
数据类FriendEntity:
@Entity(tableName = "Friends")
data class FriendEntity (
@PrimaryKey val friend_name: String ,
@ColumnInfo(name = "debt") val debt: Float )
RecyclerView的ExpenseActivity.xml:
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerList"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
ExpenseActivity.kt:
class ExpenseActivity : AppCompatActivity() {
private lateinit var binding: ActivityExpenseBinding
private lateinit var layoutManager: LinearLayoutManager
private lateinit var recyclerAdapter: FriendListAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this@ExpenseActivity,R.layout.activity_expense)
layoutManager = LinearLayoutManager(this@ExpenseActivity)
val friendsList = GetFriends(applicationContext).execute().get()
binding.txtDef.visibility = if(friendsList.size==0) View.VISIBLE else View.GONE
binding.recyclerList.visibility = if(friendsList.size!=0) View.VISIBLE else View.GONE
recyclerAdapter = FriendListAdapter(this@ExpenseActivity,friendsList)
binding.recyclerList.layoutManager = layoutManager
binding.recyclerList.adapter = recyclerAdapter
} }
我已经测试了我的GetFriends,它工作正常。
FriendListAdapter.kt:
class FriendListAdapter(val context: Context, private val itemList: ArrayList<FriendEntity>):
RecyclerView.Adapter<FriendListAdapter.FriendViewHolder>() {
private var checkList: ArrayList<FriendEntity> = arrayListOf()
class FriendViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val txtFriendName: TextView = view.findViewById(R.id.txtFriendName)
val imgCheck: ImageView = view.findViewById(R.id.imgCheck)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FriendViewHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.recycler_single_friend,parent,false)
return FriendViewHolder(view)
}
override fun getItemCount() = itemList.size
override fun onBindViewHolder(holder: FriendViewHolder, position: Int) {
val itemObject = itemList[position]
holder.txtFriendName.text = itemObject.friend_name
holder.imgCheck.setOnClickListener {
if(checkList.contains(itemObject)) {
holder.imgCheck.setImageResource(R.drawable.ic_cb_empty)
checkList.remove(itemObject)
} else {
holder.imgCheck.setImageResource(R.drawable.ic_cb_full)
checkList.add(itemObject)
}
}
} }
我遇到的问题是:
The 16th automatically changes
The 17th gets automatically clicked
此外,该行为还存在很多问题,以至于当我点击第16张图像时,它没有响应。第2次单击使其未被选中。与第17张图片相同。我猜适配器有问题。
然后,我尝试对单个项目进行较小的显示,以使我的屏幕上总共可以看到20个项目。现在,当我点击第一个图像时,将选择第24个图像,第二次单击将更改第25个图像。这意味着它会单击当前不在视图中但如何显示的项目?
[如果有人至今还不了解,我会在此处粘贴视频的GDriveLink:Link to video of the problem
我想知道如何消除此错误?
您面临的问题是由于视图持有者的重用。最简单的解决方案是在POJO类FriendEntity中创建一个布尔字段。
data class FriendEntity (
@PrimaryKey val friend_name: String ,
@ColumnInfo(name = "debt") val debt: Float
val isSelected //To store current status)
现在在绑定数据时检查此状态,并根据它设置复选框。
override fun onBindViewHolder(holder: FriendViewHolder, position: Int) {
val itemObject = itemList[position]
//Image selection will be done at binding.
if(itemObject.isSelected){
holder.imgCheck.setImageResource(R.drawable.ic_cb_full)
}else{
holder.imgCheck.setImageResource(R.drawable.ic_cb_empty)
}
holder.txtFriendName.text = itemObject.friend_name
holder.imgCheck.setOnClickListener {
//Just change the status and notify the change.
itemObject.isSelected = !itemObject.isSelected
notifyItemChanged(position)
}
Aashit Shah提供的答案肯定是一个很好的答案,并且可以很好地完成工作。但是以防万一,如果有人不想更改实体类(在我的情况下,我不想在POJO / data类中进行任何更改,因为我将FriendEntity的整个对象发送到Room Database),因此您可以解决。
您可以像这样添加一个布尔数组作为适配器类的成员变量
private val boolArray = ArrayList(Collections.nCopies(itemCount,false))
此boolArray将在本地保留布尔状态的记录。因此,我们可以按与上述相同的方式在onBindViewHolder上使用它:
override fun onBindViewHolder(holder: FriendViewHolder, position: Int) {
val itemObject = itemList[holder.adapterPosition]
holder.txtFriendName.text = itemObject.friend_name
holder.imgCheck.setImageResource(if(boolArray[holder.adapterPosition]) R.drawable.ic_cb_full else R.drawable.ic_cb_empty)
holder.imgCheck.setOnClickListener {
if(boolArray[holder.adapterposition]) {
holder.imgCheck.setImageResource(R.drawable.ic_cb_empty)
checkList.remove(itemObject)
boolArray[holder.adapterPosition] = false
} else {
holder.imgCheck.setImageResource(R.drawable.ic_cb_full)
checkList.add(itemObject)
boolArray[holder.adapterPosition] = true
}
}
}
使用此替代方法的优点是它不会更改您以前的数据库,并且此boolArray的生命周期仅是一个对象,因此具有空间效率。