Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AsyncListDiffer is not updating the recyclerview

I have a RecyclerView with an adapter that uses AssyncListDiffer. The problem I have is that the recyclerview is not updated when changes happen in the LiveData. The observer is notified but the list doesn't update.

This is my adapter:

class HourAdapter(private val interaction: HourInteraction? = null) :
RecyclerView.Adapter<HourAdapter.HourViewHolder>() {

    private val differ = AsyncListDiffer(this, DIFF_CALLBACK)

    fun submitList(list: List<Hour>?) {
        differ.submitList(list)
    }

    private fun getHourAt(position: Int): Hour {
        return differ.currentList[position]
    }

    override fun getItemCount(): Int {
        return differ.currentList.size
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): HourViewHolder {...}

    override fun onBindViewHolder(holder: HourViewHolder, position: Int) {...}

    val DIFF_CALLBACK = object : DiffUtil.ItemCallback<Hour>() {

      override fun areItemsTheSame(oldItem: Hour, newItem: Hour): Boolean {
        return (oldItem.name == newItem.name) && (oldItem.isChecked == newItem.isChecked)
        }

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

     }

    class HourViewHolder
        (
        internal val binder: HourItemBinding
    ) : RecyclerView.ViewHolder(binder.root)

}

I use the "submitList()" to submit the new list. But it doesn't work.

I looked for solutions online and basically there were 2 options:

  1. In the submitList function, call the "submitList" of AssyncListDiffer twice like this:

        differ.submitList(null)
        differ.submitList(list)
    }```
    
  2. The second option was to use ListAdapter and override the "submitList" function like this:
  override fun submitList(list: List<Hour>?) {
  super.submitList(list?.let { ArrayList(it) })
  }

The first solution works, but the recyclerview blinks whenever I update it. The second solution to override the method does not work for me.

I've been trying to fix this for days, but I can't make it work. Also, I don't want to use notifyItemChanged() or notifyDataSetChanged().

Is there another way?

like image 214
CyberUser Avatar asked May 09 '20 12:05

CyberUser


1 Answers

I came around the same thing and observed the following.

Each time AsyncListDiffer received my list; it was the same object as previously - present in memory. Hence, the differ decided nothing changed and did not submit the updated list.

My list contained one object inside, and for each submission attempt I was changing one field. The object and the list of course remained the same.

So, I wondered why option number 2 did not work, and turned out that I needed to be a little more expressive:

submitList(it.map {
    it.copy()
})

Otherwise, Kotlin would not make a deep copy of the object.

like image 157
pratclot Avatar answered Sep 28 '22 07:09

pratclot