英文:
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 "diffcallback".
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<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
}
}
// 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 => THIS IS SUPPOSED TO UPDATE THE ITEMS IN THE RECYCLERVIEW
}
答案1
得分: 3
- 你往列表中添加了新元素
- 你通知列表已经改变
- differ比较了"新"列表和"旧"列表
- 在这两种情况下,它是相同的实例,所以不可能有任何差异 -> 没有更新
你基本上通过偷偷修改其列表来绕过了differ。
作为一个快速的解决办法,你可以使用:
set(value) {
differ.submitList(value.toList()) //复制
}
但你真的需要重新考虑列表的工作方式。不可变性是防止此类问题的方法。
此外,你发布的代码缺少某些内容: vehicleInformationList.add
不应该是可能的,因为该列表是不可变的。不可变性是通过vehicleInformationList = vehicleInformationList.plus(vehicleInformation)
来保持的。
英文:
- you add new element to the list
- you notify that the list had changed
- differ compares the "new" list with the "old" list
- 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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论