RecyclerView 中的列表在列表更改时未更新。

huangapple go评论68阅读模式
英文:

List in RecyclerView is not updating when List is changed

问题

I understand that you want the translated content from your provided code. Here's the translated code:

为什么在RecyclerView中添加新对象到列表时列表不会更新我已经使用了DiffUtil并在实现的方法中设置了断点我在`differ.submitList(value)`中得到了更新后的值但在diffcallback中没有在第一次创建列表时没有问题但当我向列表添加另一个元素时它不会反映出来请查看我的RecyclerView适配器

```kotlin
    class VehiclesInvolvedAdapter : RecyclerView.Adapter<VehiclesInvolvedAdapter.VehiclesInvolvedViewHolder>() {
        inner class VehiclesInvolvedViewHolder(itemView: View): RecyclerView.ViewHolder(itemView)
    
        private val diffCallback = object : DiffUtil.ItemCallback<VehicleInformation>() {
            override fun areItemsTheSame(
                oldItem: VehicleInformation,
                newItem: VehicleInformation
            ): Boolean {
                return oldItem.id == newItem.id
            }
    
            override fun areContentsTheSame(
                oldItem: VehicleInformation,
                newItem: VehicleInformation
            ): Boolean {
                return oldItem == newItem
            }
        }
    
        private val differ = AsyncListDiffer(this, diffCallback)
        var vehicleInformationList: List<VehicleInformation>
            get() = differ.currentList
            set(value) {
                differ.submitList(value)
            }
    
        override fun getItemCount() = differ.currentList.size
    
        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): VehiclesInvolvedViewHolder {
            return VehiclesInvolvedViewHolder(
                LayoutInflater.from(parent.context).inflate(
                    R.layout.item_vehicle_involved,
                    parent,
                    false
                )
            )
        }
    
        override fun onBindViewHolder(holder: VehiclesInvolvedViewHolder, position: Int) {
            val vehicleInformation = vehicleInformationList[position]
    
            holder.itemView.apply {
                var btnVehicle = findViewById<TextView>(R.id.btnVehicle)
                btnVehicle.text = vehicleInformation.plateNumber
    
                setOnClickListener {
                    onItemClickListener?.let { it(vehicleInformation) }
                }
            }
        }
    
        private var onItemClickListener: ((VehicleInformation) -> Unit)? = null
    
        fun setOnItemClickListener(listener: (VehicleInformation) -> Unit) {
            onItemClickListener = listener
        }
    }

    // 这是我如何向列表添加另一个对象
    private fun setupRecyclerView() = binding!!.rvVehicleInvolved.apply {
    	vehicleInvolvedAdapter = VehiclesInvolvedAdapter()
    	adapter = vehicleInvolvedAdapter
    	layoutManager = LinearLayoutManager(requireContext(), LinearLayoutManager.HORIZONTAL, false)
    }
    
    private fun addOBject() {
    	vehicleInformationList.add(vehicleInformation)
    	vehicleInvolvedAdapter.vehicleInformationList = vehicleInformationList // 这应该更新RecyclerView中的项目
    }

<details>
<summary>英文:</summary>
Why is it that my list in RecyclerView does not update when I add a new object into the list? I have used DiffUtil and placed a break point in the implemented methods and I get an updated value in the `differ.submitList(value)` but not in the &quot;diffcallback&quot;. 
In the first instance I create the List, I get no issues but when I add another element to the List, it does not reflect. Please see my RecyclerView Adapter
```kotlin
class VehiclesInvolvedAdapter : RecyclerView.Adapter&lt;VehiclesInvolvedAdapter.VehiclesInvolvedViewHolder&gt;(){
inner class VehiclesInvolvedViewHolder(itemView: View): RecyclerView.ViewHolder(itemView)
private val diffCallback = object : DiffUtil.ItemCallback&lt;VehicleInformation&gt;() {
override fun areItemsTheSame(
oldItem: VehicleInformation,
newItem: VehicleInformation
): Boolean {
return oldItem.id == newItem.id
}
override fun areContentsTheSame(
oldItem: VehicleInformation,
newItem: VehicleInformation
): Boolean {
return oldItem == newItem
}
}
private val differ = AsyncListDiffer(this, diffCallback)
var vehicleInformationList: List&lt;VehicleInformation&gt;
get() = differ.currentList
set(value) {
differ.submitList(value)
}
override fun getItemCount() = differ.currentList.size
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): VehiclesInvolvedViewHolder {
return VehiclesInvolvedViewHolder(
LayoutInflater.from(parent.context).inflate(
R.layout.item_vehicle_involved,
parent,
false
)
)
}
override fun onBindViewHolder(holder: VehiclesInvolvedViewHolder, position: Int) {
val vehicleInformation = vehicleInformationList[position]
holder.itemView.apply {
var btnVehicle = findViewById&lt;TextView&gt;(R.id.btnVehicle)
btnVehicle.text = vehicleInformation.plateNumber
setOnClickListener {
onItemClickListener?.let { it(vehicleInformation) }
}
}
}
private var onItemClickListener: ((VehicleInformation) -&gt; Unit)? = null
fun setOnItemClickListener(listener: (VehicleInformation) -&gt; Unit) {
onItemClickListener = listener
}
}
// This is how I add another object to the List
private fun setupRecyclerView() = binding!!.rvVehicleInvolved.apply {
vehicleInvolvedAdapter = VehiclesInvolvedAdapter()
adapter = vehicleInvolvedAdapter
layoutManager = LinearLayoutManager(requireContext(), LinearLayoutManager.HORIZONTAL, false)
}
private fun addOBject() {
vehicleInformationList.add(vehicleInformation)
vehicleInvolvedAdapter.vehicleInformationList = vehicleInformationList =&gt; THIS IS SUPPOSED TO UPDATE THE ITEMS IN THE RECYCLERVIEW
}

答案1

得分: 3

  1. 你往列表中添加了新元素
  2. 你通知列表已经改变
  3. differ比较了"新"列表和"旧"列表
  4. 在这两种情况下,它是相同的实例,所以不可能有任何差异 -> 没有更新

你基本上通过偷偷修改其列表来绕过了differ。

作为一个快速的解决办法,你可以使用:

set(value) {
    differ.submitList(value.toList()) //复制
}

但你真的需要重新考虑列表的工作方式。不可变性是防止此类问题的方法。

此外,你发布的代码缺少某些内容: vehicleInformationList.add 不应该是可能的,因为该列表是不可变的。不可变性是通过vehicleInformationList = vehicleInformationList.plus(vehicleInformation)来保持的。

英文:
  1. you add new element to the list
  2. you notify that the list had changed
  3. differ compares the "new" list with the "old" list
  4. it's same instance in both cases, so there can't be any differences -> no update

You've basically circumvented the differ by sneakily modifying its list.

As a quick hack you can use:

set(value) {
differ.submitList(value.toList()) //makes a copy
}

But you really need to rethink how lists work. Immutability is the way to prevent such problems.

Also, the code you've posted is missing something: vehicleInformationList.add shouldn't be possible, because the list is immutable. Immutability is preserved with vehicleInformationList = vehicleInformationList.plus(vehicleInformation)

答案2

得分: 2

不要翻译的代码部分:

You're not notifying the adapter of the change made in the list, checkout the variety of notify functions in the documentation (https://developer.android.com/reference/androidx/recyclerview/widget/RecyclerView.Adapter) and pick the most suitable one. I'll assume that the new list is completely different from the previous one and offer you this change:

private fun addOBject() {
vehicleInformationList.add(vehicleInformation)
vehicleInvolvedAdapter.vehicleInformationList = vehicleInformationList
vehicleInvolvedAdapter.notifyDataSetChanged()
}

I recommend that you don't use notifyDataSetChanged() due to performance issues on larger lists, instead use notifyItemRangeChanged(int positionStart, int itemCount) to update only the items that were added or changed.

英文:

You're not notifying the adapter of the change made in the list, checkout the variety of notify functions in the documentation (https://developer.android.com/reference/androidx/recyclerview/widget/RecyclerView.Adapter) and pick the most suitable one. I'll assume that the new list is completely different from the previous one and offer you this change:

private fun addOBject() {
vehicleInformationList.add(vehicleInformation)
vehicleInvolvedAdapter.vehicleInformationList = vehicleInformationList
vehicleInvolvedAdapter.notifyDataSetChanged()
}

I recommend that you don't use notifyDataSetChanged() due to performance issues on larger lists, instead use notifyItemRangeChanged(int positionStart, int itemCount) to update only the items that were added or changed.

答案3

得分: 1

The vehicleInvolvedAdapter 需要在每次 vehicleInformationList 被更新时得到通知。请用以下代码替换您的 addOBject 函数:

private fun addOBject() {
    vehicleInformationList.add(vehicleInformation)
    vehicleInvolvedAdapter.vehicleInformationList = vehicleInformationList 
    vehicleInvolvedAdapter.notifyDataSetChanged()
}

阅读以下链接:Adapters

英文:

The vehicleInvolvedAdapter needs to be notified every time the vehicleInformationList is updated. Replace your addOBject function with the following:

private fun addOBject() {
vehicleInformationList.add(vehicleInformation)
vehicleInvolvedAdapter.vehicleInformationList = vehicleInformationList 
vehicleInvolvedAdapter.notifyDataSetChanged()
}

Read the following link: Adapters

huangapple
  • 本文由 发表于 2023年4月4日 14:47:39
  • 转载请务必保留本文链接:https://go.coder-hub.com/75926262.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定