> ## Content Index
> Fetch the complete content index at: https://lucas-schiavini.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# Daily Dispatch 22 - ListAdapter to the Rescue
- URL: https://lucas-schiavini.com/daily-dispatch-22-listadapter-for-the-rescue/
- Published: 2022-04-27T01:00:40.000Z
- Updated: 2022-08-11T19:34:09.000Z
- Author: Lucas Schiavini
- Tags: android, kotlin, listrendering, recyclerview, dailydispatch, #Import 2026-08-11 14:49

It’s been a while since I’ve written about some “normal” Android Development.

Today I followed a lead on [DiffUtil](https://developer.android.com/reference/androidx/recyclerview/widget/DiffUtil?ref=lucas-schiavini.com), a library that a senior developer told me about. It is supposed to be used in Recycler views with adapters to avoid having to call notifyAllDataChanged() and having some uneasy visual bugs.

So I looked into it and found some lovely blog posts on the matter.

One that I found really enlightening was [this one](https://medium.com/@trionkidnapper/recyclerview-more-animations-with-less-code-using-support-library-listadapter-62e65126acdb?ref=lucas-schiavini.com).

So I went back to my [MovieApp](https://github.com/lschiavini/MovieApp?ref=lucas-schiavini.com) to fix my visual bugs.

This is the old way of using RecyclerView.Adapter:

```kotlin
class MovieListAdapter(private var moviesList: ArrayList) : RecyclerView.Adapter<MovieListAdapter.MovieViewHolder>(), MovieClickListener 
{    
    private lateinit var accessView : MovieItemBinding
    @SuppressLint("NotifyDataSetChanged")    
    fun updateMoviesList(newMoviesList: List) {
    	moviesList.clear()        
        moviesList.addAll(newMoviesList)
        notifyDataSetChanged()
    }
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MovieViewHolder {
        val inflater = LayoutInflater.from(parent.context)
        val view = DataBindingUtil.inflate(inflater, R.layout.movie_item, parent, false)
        accessView = view
        return MovieViewHolder(view)
    }
    override fun onBindViewHolder(holder: MovieViewHolder, position: Int) {        	val item = moviesList[position]
      accessView.movie = item
      accessView.listener = this
    }
    override fun onMovieClicked(v: View) {
    	val id = v.movieId.text.toString()
        val action = MoviesListFragmentDirections.actionMovieFragmentToMovieDetail()       
        action.movieId = id.toInt()        			
        findNavController(v).navigate(action)
    }
    override fun getItemCount(): Int = moviesList.size    
    
    inner class MovieViewHolder(binding: MovieItemBinding) : RecyclerView.ViewHolder(binding.root) {
    	var movie: Movie? = binding.movie
        var listener: MovieClickListener? = binding.listener
    }
}
```

Now there was a lot going on here. But the worst offender was the updateMoviesList calling `notifyDataSetChanged`. What this does is forces the UI to re-render the whole view, even on items that haven’t changed from the previous movie list.

So what was the solution? First I implemented this Callback class, that uses [DiffUtil](https://developer.android.com/reference/androidx/recyclerview/widget/DiffUtil?ref=lucas-schiavini.com). Which is basically a class that facilitates comparison between items. And more importantly, will be used later on the new Adapter.

```kotlin
class MovieListDiffCallback : DiffUtil.ItemCallback() {
    override fun areItemsTheSame(oldItem: Movie, newItem: Movie): Boolean {
    	return oldItem.id == newItem.id
    }
    override fun areContentsTheSame(oldItem: Movie, newItem: Movie): Boolean {
    	return oldItem == newItem
    }
}
```

After this was done, I went to restructure my MovieListAdapter class, so it inherits from ListAdapter, which is a improved version of dealing with lists. Less boilerplate code and integration with [DiffUtil](https://developer.android.com/reference/androidx/recyclerview/widget/DiffUtil?ref=lucas-schiavini.com).

Here’s the new declaration:

```kotlin
class MovieListAdapter(
) : ListAdapter<Movie, MovieListAdapter.MovieViewHolder>(MovieListDiffCallback()) {

    ...

    inner class MovieViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        ...
    }
}
```

As you can see I took some liberty with MovieViewHolder as well, switched from binding to view. I decided to start using viewBinding instead of databinding to facilitate my life later on.

Here’s the new functioning code for the MovieListAdapter:

```kotlin
class MovieListAdapter(
) : ListAdapter<Movie, MovieListAdapter.MovieViewHolder>(MovieListDiffCallback()) {

    lateinit var view : View  

    private fun clickListener (v: View) {  
        val id = v.movieId.text.toString()  
        val action = MoviesListFragmentDirections.actionMovieFragmentToMovieDetail()  
        action.movieId = id.toInt()  
        findNavController(v).navigate(action)  
    }  
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MovieViewHolder {  
        val inflater = LayoutInflater.from(parent.context)  
        val binding = MovieItemBinding.inflate(inflater, parent, false)  
        val view = binding.root  
        return MovieViewHolder(view)  
    }  
    override fun onBindViewHolder(holder: MovieViewHolder, position: Int) {  
        holder.bind(getItem(position)) { newView -> clickListener(newView) }  
    }  

    inner class MovieViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {  

        fun bind(newMovie: Movie, clickListener: (View) -> Unit) {  
            itemView.apply {  
                loadImage(imageView, newMovie.posterPath)  
                movieId.text = newMovie.id.toString()  
                title.text = newMovie.title  
                releaseDate.text = newMovie.releaseDate  
                setOnClickListener(clickListener)  
            }  
        }  

    }  
}
```

There’s only one subtle detail about calling the movieListAdapter to update the list, we need to change any old invocations of ***adapter.updateMoviesList(newList)*** to ***adapter.submitList(newList)***.

And that is it for today, see you tomorrow (whenever that is 😉 ).