List Adapter diffutil not updating the list item in recyclerview.
It works when I add or remove a item from the list. But not updating the any particular value like isSelected : Boolean = false
in object class
How to update the recyclerview view when one of the object class in list is changed like value Boolean changes in one object class
Thankyou
Adapter Class Below
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) })
}
}
First of, the implementation of areContentsTheSame
and areItemsTheSame
probably needs to be switched. areContentsTheSame
is the one that checks if things in your items are different. areItemsTheSame
is about whether it is the same item. If the items have an id you might want to compare them instead of the item themselves. But that alone probably won't fix your issue.
The thing is, ListAdapter works best if the list has items that are immutable. Ideally you want to submit a new list every time you call submitList
. Because if you change a property like isSelected
in the existing lisk and simply call submitList with that same list nothing will happen.
So what you want to do is instead of changing the isSelected
property you need to create a copy of the list and in that copy alone you change the isSelected
and pass the copy to submitList
.
This can be tedious to make. An alternative ugly workaround that might work is to add a second property maybe called oldIsSelected
and only change that one in the DiffUtil itself, like this
override fun areContentsTheSame(oldItem: CategoryModel, newItem: CategoryModel): Boolean {
val result = oldItem.oldIsSelected == newItem.isSelected
newItem.oldIsSelected = newItem.isSelected
return result
}