What is DiffUtil?
A utility class that finds the difference between two lists and provides the updated list as an output. We can use this utility class to notify updates to a RecyclerView Adapter.
When the content of our list gets changed, we have to call notifyDataSetChanged for getting the updates but it is very costly. There are so many iterations for getting the job done in the case of notifyDataSetChanged.
As of 24.2.0, RecyclerView Support Library, the v7 package offers a utility class called DiffUtil. It does its job perfectly. It is based on Eugene Myers’ algorithm.
Comparison with notifyDataSetChanged
If you know the implementation of RecyclerView
you may also know that below mentioned method will be required to notify the changes to the adapter.
notifyItemChanged
notifyItemInserted
notifyItemRemoved
And their corresponding Range
variations
notifyItemRangeChanged
notifyItemRangeInserted
notifyItemRangeRemoved
Their names explain their purpose pretty well. According to the official documentation, they are significantly more efficient than the famous notifyDataSetChanged(). DiffUtil uses these methods to notify the RecyclerView for any changes in the data set
Let’s take a scenario, where we are using some filtration on data. Here we will sort data according to the rating.
DataRepository.class
DiffUtil.Callback is an abstract class that has both abstract and non-abstract methods in it. Let’s take a look at the adapter and callback class first.
RatingAdapter.class
Let’s understand the RatingDiffCallback.class methods.
getOldListSize()– This method will return the size of the old list.
getNewListSize()– This method will return the size of the new list.
areItemsTheSame(int oldItemPosition, int newItemPosition)– This callback method decides whether two objects are representing same items or not.
areContentsTheSame(int oldItemPosition, int newItemPosition)– This callback method decides that two items have same data or not. This method will only be called if the return type is true.
getChangePayload(int oldItemPosition, int newItemPosition)– If areItemTheSame returns true and areContentsTheSame returns false DiffUtil utility calls this method to get a payload about the change.
It is recommended that for a large amount of data in the list, you should do the calculation part in a background thread as it may throw an ANR exception.
Why use DiffUtil?
Here is the performance chart which illustrates that using DiffUtil is better in a case of RecyclerView. These results are based on Nexus 5X with M-
- 100 items and 10 modifications: avg: 0.39 ms, median: 0.35 ms
- 100 items and 100 modifications: 3.82 ms, median: 3.75 ms
- 100 items and 100 modifications without moves: 2.09 ms, median: 2.06 ms
- 1000 items and 50 modifications: avg: 4.67 ms, median: 4.59 ms
- 1000 items and 50 modifications without moves: avg: 3.59 ms, median: 3.50 ms
- 1000 items and 200 modifications: 27.07 ms, median: 26.92 ms
- 1000 items and 200 modifications without moves: 13.54 ms, median: 13.36 ms
Due to implementation constraints, the max size of the list can be 2^26.
Conclusion
DiffUtil utility class finds the difference between the provided old and new lists and dispatches the updates to the adapter.