Android Recycler Adapter位置不正常:onClick处理不正常

问题描述 投票:1回答:2

我有一个回收站视图,可以从数据库中获取详细信息。房间数据库给出了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)
            }
        }
     } }

我遇到的问题是:

I tap on 1st element

The 16th automatically changes

I tap 2nd image

The 17th gets automatically clicked

此外,该行为还存在很多问题,以至于当我点击第16张图像时,它没有响应。第2次单击使其未被选中。与第17张图片相同。我猜适配器有问题。

然后,我尝试对单个项目进行较小的显示,以使我的屏幕上总共可以看到20个项目。现在,当我点击第一个图像时,将选择第24个图像,第二次单击将更改第25个图像。这意味着它会单击当前不在视图中但如何显示的项目?

[如果有人至今还不了解,我会在此处粘贴视频的GDriveLink:Link to video of the problem

我想知道如何消除此错误?

android kotlin android-recyclerview recycler-adapter
2个回答
2
投票

您面临的问题是由于视图持有者的重用。最简单的解决方案是在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)
}

0
投票

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的生命周期仅是一个对象,因此具有空间效率。

© www.soinside.com 2019 - 2024. All rights reserved.