列表适配器 Diff Util 不更新 Recyclerview 中的列表项

Sum*_*nan 8 android listadapter kotlin android-recyclerview android-diffutils

列表适配器 diffutil 未更新 recyclerview 中的列表项。

当我从列表中添加或删除项目时它会起作用。isSelected : Boolean = false但不会像对象类中那样更新任何特定值

当列表中的对象类之一发生更改(例如一个对象类中的布尔值更改)时,如何更新 recyclerview 视图

谢谢

下面的适配器类

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) })
    }
}

Run Code Online (Sandbox Code Playgroud)

Ivo*_*ers 0

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

问题是,如果列表中包含不可变的项目,ListAdapter 效果最佳。理想情况下,您希望每次致电时都提交一份新列表submitList。因为如果您更改现有链中的属性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
    }
Run Code Online (Sandbox Code Playgroud)