android - DiffUtil.ItemCallback 不更新项目位置(删除后)

标签 android android-recyclerview android-diffutils android-listadapter

我使用 ListAdapter 的绑定(bind)和 DiffUtil.ItemCallback 的定义。删除项目(至少 2 个)时出现 IndexOutOfBoundsException。 列表的更新有效(删除后元素的数量确实是 N-1)但不是项目的位置,保留的是调用。因此在调用 getItem(position) 时抛出异常(在 onBindViewHolder 中)。注意:getItem(position) 之前的 getItemCount() 日志显示该列表包含 N-1 个元素。 我创建了一个小仓库:https://github.com/jeremy-giles/DiffListAdapterTest (与我的项目具有相同的配置)重现了问题。

ItemAdapter 类

class ItemAdapter(
    var listener: ListAdapterListener) : DataBindingAdapter<Item>(DiffCallback()) {

    class DiffCallback : DiffUtil.ItemCallback<Item>() {

        override fun areItemsTheSame(oldItem: Item, newItem: Item): Boolean {
           return oldItem == newItem
        }

        override fun areContentsTheSame(oldItem: Item, newItem: Item): Boolean {
           return oldItem == newItem
        }
    }

    override fun getItemViewType(position: Int) = R.layout.recycler_item

    override fun onBindViewHolder(holder: DataBindingViewHolder<Item>, position: Int) {
        super.onBindViewHolder(holder, position)

        holder.itemView.tv_position.text = "Pos: $position"

        holder.itemView.setOnLongClickListener {
            Timber.d("List item count: ${itemCount}, position: $position")
            listener.onLongViewClick(getItem(position), position)
        }
    }

    interface ListAdapterListener {
        fun onLongViewClick(item: Item, position: Int) : Boolean
    }
}

BindingUtils 类

abstract class DataBindingAdapter<T>(diffCallback: DiffUtil.ItemCallback<T>) :
    ListAdapter<T, DataBindingViewHolder<T>>(diffCallback) {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): DataBindingViewHolder<T> {
        val layoutInflater = LayoutInflater.from(parent.context)
        val binding = DataBindingUtil.inflate<ViewDataBinding>(layoutInflater, viewType, parent, false)

        return DataBindingViewHolder(binding)
    }

    override fun onBindViewHolder(holder: DataBindingViewHolder<T>, position: Int) {
        holder.bind(getItem(position))
    }
}

class DataBindingViewHolder<T>(private val binding: ViewDataBinding) :
    RecyclerView.ViewHolder(binding.root) {

    fun bind(item: T) {
        binding.setVariable(BR.item, item)
        binding.executePendingBindings()
    }
}

在我的 MainActivity 类中,我使用 LiveData 更新 recyclerView

itemViewModel.getListObserver().observe(this, Observer {
        Timber.d("List Observer, items count ${it.size}")
        itemAdapter.submitList(it.toList())
    })

最佳答案

在您的 onBindViewHolder 中,将“position”的用法更新为“holder.getAdapterPosition()”:

override fun onBindViewHolder(holder: DataBindingViewHolder<Item>, position: Int) {
        super.onBindViewHolder(holder, position)

        holder.itemView.tv_position.text = "Pos: $position"

        holder.itemView.setOnLongClickListener {
            Timber.d("List item count: ${itemCount}, position: $position")
            listener.onLongViewClick(getItem(holder.getAdapterPosition()), holder.getAdapterPosition())
        }
    }

关于android - DiffUtil.ItemCallback 不更新项目位置(删除后),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59560135/

相关文章:

android - 如何在 Android 上的 RecyclerViewAdapter 中使用 DiffUtils

android - 协程、异步 DiffUtil 和不一致检测错误

java - 如何在android中的同一个recyclerview中使用相同的字段或属性填充不同的对象

java - 在Android上所有可滑动的应用程序顶部创建一个边缘热点

android - Android Studio无法同步Gradle项目

android - google 尝试登录 Android idToken :null

android - getAdapterPosition() 不返回项目在 RecyclerView 中的位置

java - 安卓 : Setting text in recycler view

java - 如何修复使用 DiffUtil 向 ListUpdateCallback 发送更新时得到的错误位置

Android Wear Notification 操作错误消息