Home > Blockchain >  ListAdapter submitList not updating
ListAdapter submitList not updating

Time:11-25

I have this issue with the pagination infinite scroll in RecyclerView, I am adding all new item using .addAll()

 movieList.addAll(it.movieList)
 adapter.submitList(movieList)
 Log.wtf("WTF", movieList.size.toString())

The size keeps increasing whenever we get a success response from API which indicates that the list is indeed being populated but the item in RecyclerView stays the same and submitList() seems to work only at first call.

Here is my DiffUtil class and the Adapter

class DiffUtilMovies : DiffUtil.ItemCallback<MovieItem>() {

    // DiffUtil uses this test to help discover if an item was added, removed, or moved.
    override fun areItemsTheSame(oldItem: MovieItem, newItem: MovieItem): Boolean {
        return oldItem.id == newItem.id
    }

    // Check whether oldItem and newItem contain the same data; that is, whether they are equal.
    // If there are differences between oldItem and newItem, this code tells DiffUtil that the item has been updated.
    override fun areContentsTheSame(oldItem: MovieItem, newItem: MovieItem): Boolean {
        // Check for now if there is a difference on the price, removing specific fields
        // means checking all the data for changes
        return oldItem.title == newItem.title
    }

}


class MovieAdapter(private val context: Context) : ListAdapter<MovieItem, MovieAdapter.ItemView>(DiffUtilMovies()) {

    private var isDetached: Boolean = false

    class ItemView(itemView: MovieCardBinding) : RecyclerView.ViewHolder(itemView.root) {
        val titleTxt = itemView.titleTxt
        val rateTxt = itemView.rateTxt
        val rateBar = itemView.rateBar
        val imageThumb = itemView.thumbnail
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemView {
        return ItemView(
            MovieCardBinding.inflate(
                LayoutInflater.from(parent.context),
                parent,
                false
            )
        )
    }

    override fun onBindViewHolder(holder: ItemView, position: Int) {
        holder.apply {

            val movieItem = getItem(position)

            titleTxt.text = movieItem.title
            rateTxt.text = movieItem.voteAverage.toString()

            val rateAvg = movieItem.voteAverage?.toFloat() ?: run {
                0.0f
            }

            rateBar.rating = rateAvg/2

            if (!isDetached)
                GlideApp.with(context)
                    .load(context.getString(R.string.image_link,AppConfig.image_endpoint, movieItem.posterPath))
                    .thumbnail(GlideApp.with(context).load(R.drawable.loading).centerCrop())
                    .error(R.drawable.no_image)
                    .into(imageThumb)

            this.itemView.setOnClickListener {

                try {

//                    context.startActivity(Intent(context, AssetInfoActivity::class.java).apply {
//                        putExtra(context.getString(R.string.assets), movieItem)
//                    })

                }
                catch (ignored: Exception){
                    // The user probably already leave before the activity started
                }

            }

        }
    }

    override fun onDetachedFromRecyclerView(recyclerView: RecyclerView) {
        super.onDetachedFromRecyclerView(recyclerView)
        isDetached = true
    }
}

CodePudding user response:

ListAdapter doesn’t work with mutable lists. This is because if you modify the contents of the List, when it tries to compare the contents of the old list and new list, it’s comparing the same list to itself. There is no old list instance that still holds the old contents, so it cannot detect any differences.

Instead of mutating the original list, you should create a new one, for example

movieList = movieList   it.movieList
adapter.submitList(movieList)

Alternatively, you can use a mutable backing list, but always create a copy when passing it to submitList. You must use a copy even the very first time you pass the List so it is never referring to your mutable List.

movieList.addAll(it.movieList)
adapter.submitList(movieList.toList())
  • Related