The Right Way to update the Items in a RecyclerView

The Right Way to update the Items in a RecyclerView

Image source

Prerequisite: In order to get the most out of this article, you should be familiar with the concept of RecyclerView in Android Development.

A List is a common feature in Android applications. Understanding how to optimize its implementation in order to ensure a polished User Experience, is a very essential part of Android Development.

What is DiffUtil?

DiffUtil is a utility class. It takes two lists (consisting of an old list and a new list) and compares them. It uses an algorithm called Eugene W. Myers difference algorithm to figure out the minimum number of changes to make in the old list in order to produce the new list.

Fun fact: I found out that Eugene W. Myers difference algorithm is the default diff algorithm used by Git. You can read up on it via the original paper.

DiffUtil vs notifyDataSetChanged()

An application with a poor performance and a poor User Experience can frustrate a user.

Prior to DiffUtil, Android developers made use of notifyDataSetChanged() to notify the RecyclerView when the list undergoes changes. It tells the RecyclerView that the entire list is potentially invalid. As a result, RecyclerView re-draws and re-binds every item in the list, which can be a really expensive operation.

notifyDataSetChanged() causes a lot of screen updates which can lead to really poor performance for your application. In extreme cases, this might show up as a flicker when the screen updates and can make the users have trouble while scrolling. This can really frustrate the users.

To fix this issue, RecyclerView needs to know exactly what changed in the list. Thanks to DiffUtil and its ability to compare two lists, RecyclerView can now redraw only changed items and animate these changes by default. This takes lesser time and can greatly improve the performance of Android applications.

DiffUtil Implementation

  • Create the datatype of your list. In this example, a list showing different products is used

  • Create a custom DiffUtil.Callback class which extends the DiffUtil.Callback class. The DiffUtil.Callback abstract class is a class that calculates the difference between two lists. It has five public methods:

areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): This is called by the DiffUtil to determine if the contents of an item has changed. This method checks whether two items have the same data. DiffUtil gives a callback here in case you want to perform a custom check for equality. This example uses the equality (==) sign because of the Product data class. Data classes in Kotlin automatically define the equals method

areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): This is called by the DiffUtil to determine if two objects represent the same item. In other words, it is called by the DiffUtil to check if two items have the same id

getChangePayload(oldItemPosition: Int, newItemPosition: Int): This is called by the DiffUtil to get a payload about the change that occurs if areItemsTheSame(oldItemPosition: Int, newItemPosition:Int) returns true for two items and areContentsTheSame(OldItemPosition: Int, newItemPosition: Int) returns false.

getNewListSize(): This returns the size of the new list.

getOldListSize(): This returns the size of the old list.

  • Create a custom ListAdapter class which extends ListAdapter. This helps you to build a RecyclerView adapter that is backed by a list. ListAdapter helps the adapter in keeping track of the list. The ListAdapter has two generic items (the list data type and the view holder). The viewholder takes in the DiffItemCallback as its constructor parameter

  • Notify the adapter when changes occur in the list. This is achieved by using the ListAdapter submitList() method

Conclusion

I hope that you will find this article helpful and that you will start making use of DiffUtil in your RecyclerView for a better application performance and User Experience.

Did you find this article valuable?

Support Rita Okonkwo by becoming a sponsor. Any amount is appreciated!