List Adapter Diff Util 不更新 Recyclerview 中的列表项

List Adapter Diff Util not updating the List Item in Recyclerview

List Adapter diffutil 未更新 recyclerview 中的列表项。

当我从列表中添加或删除项目时,它会起作用。但不更新对象 class

中的任何特定值,例如 isSelected : Boolean = false

当列表中的一个对象 class 发生变化时如何更新 recyclerview 视图,例如一个对象中的布尔值变化 class

谢谢

适配器Class低于

class CategoryMainAdapter(
    var itemClick : CategoryItemClick,
    var screenWidth : Int = 0
) : ListAdapter<CategoryModel, CategoryMainAdapter.CategoryMainViewHolder>(CategoryMainDiffUtils()) {

    inner class CategoryMainViewHolder(val binding : CategorySingleListLayoutBinding) : RecyclerView.ViewHolder(binding.root)

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CategoryMainViewHolder {
        val binding = CategorySingleListLayoutBinding.inflate(LayoutInflater.from
            (parent.context),
            parent,
            false
        )
        return CategoryMainViewHolder(binding)
    }

    override fun onBindViewHolder(holder: CategoryMainViewHolder, position: Int) {
        val model = getItem(position)
        holder.apply {
            binding.apply {
                mainLinearLayout.layoutParams.apply {
                    width = ((screenWidth*22.5).toInt())/100
                    height = (((screenWidth*22.5)/100)*1.2).toInt()
                }
                categoryName.text = model.name
                backgroundColor.setBackgroundColor(model.colorCode)
                categoryImage.load(getImageCorrectImage(model.image, model.secondaryImage)) {
                    error(R.drawable.ic_food_place_holder)
                }

                if (model.isSelected) {
                    categoryName.setTextColor(ContextCompat.getColor(categoryName.context, R.color.main_blue))
                    selectedView.setBackgroundResource(R.drawable.main_blue_curved_bg)
                    categoryImage.apply {
                        animation = AnimationUtils.loadAnimation(context, R.anim.category_zoom_in_anim)
                        setPadding(0, 0, 0, 0)
                    }
                } else {
                    categoryName.setTextColor(setColorByAttrProgrammatically(categoryName.context, R.attr.colorOnSecondary))
                    selectedView.setBackgroundResource(android.R.color.transparent)
                    categoryImage.apply {
                        animation = AnimationUtils.loadAnimation(context, R.anim.category_zoom_out_anim)
                        setPadding(1, 1, 1, 1)
                    }
                }
            }
            itemView.apply {
                setOnClickListener {
                    itemClick.onCategoryClick(model)
                }
            }
        }
    }


    class CategoryMainDiffUtils : DiffUtil.ItemCallback<CategoryModel>() {
        override fun areItemsTheSame(oldItem: CategoryModel, newItem: CategoryModel): Boolean {
            return oldItem.isSelected == newItem.isSelected
        }

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

    }

    override fun submitList(list: MutableList<CategoryModel>?) {
        super.submitList(list?.let { ArrayList(it) })
    }
}

更改后属性您必须更新适配器数据列表并调用。

adapter.notifyDataSetChanged()

尝试将您的 DiffUtil 更新为:

class CategoryMainDiffUtils : DiffUtil.ItemCallback<CategoryModel>() {
    override fun areItemsTheSame(oldItem: CategoryModel, newItem: CategoryModel): Boolean {
        return oldItem.id == newItem.id // or compare something unique
    }

    override fun areContentsTheSame(oldItem: CategoryModel, newItem: CategoryModel): Boolean {
        return oldItem == newItem // or if data class is large, compare only things that might change, also please note that only data class on kotlin has auto generated equals() method
    }

}

首先,areContentsTheSameareItemsTheSame 的实现可能需要切换。 areContentsTheSame 是检查您的物品中的东西是否不同的那个。 areItemsTheSame是关于是否是同一项。如果项目有一个 id,你可能想要比较它们而不是项目本身。但仅此一项可能无法解决您的问题。

事实是,如果列表包含不可变的项目,ListAdapter 的效果最好。理想情况下,您希望每次调用 submitList 时都提交一个新列表。因为如果你在现有的 lisk 中更改 属性 就像 isSelected 并简单地使用相同的列表调用 submitList 什么都不会发生。

所以您要做的不是更改 isSelected 属性,而是需要创建列表的副本,仅在该副本中更改 isSelected 并通过复制到 submitList.

制作起来可能很乏味。另一种可能有效的丑陋解决方法是添加第二个 属性 可能称为 oldIsSelected 并且只在 DiffUtil 本身中更改那个,像这样

    override fun areContentsTheSame(oldItem: CategoryModel, newItem: CategoryModel): Boolean {
        val result = oldItem.oldIsSelected == newItem.isSelected
        newItem.oldIsSelected = newItem.isSelected
        return result
    }