Recycler View: DiffUtil
DiffUtil is a utility class that can calculate the difference between two lists and output a list of update operations that converts the first list into the second one. It can be used to calculate updates for a RecyclerView Adapter. DiffUtil does not call each and every row. Instead, it updates only those rows that are different between the Lists of values.
DiffUtil is more efficient than notifyDataSetChanged(). When the content of our list gets changed, we have to call notifyDataSetChanged() to get the updates but it is very costly. There are so many iterations for getting the job done in the case of notifyDataSetChanged(). Here, DiffUtil class comes into picture it updates only those rows that are different between the list of values.
DiffUtil vs notifyDataSetChanged

How to use?
DiffUtil.Callback is an abstract class and used as callback class by DiffUtil while calculating the difference between two lists. It has four abstract methods and one non-abstract method. You have to extend it and override all its methods.
- getOldListSize()– Return the size of the old list.
- getNewListSize()– Return the size of the new list.
- areItemsTheSame(int oldItemPosition, int newItemPosition)– It decides whether two objects are representing same items or not.
- areContentsTheSame(int oldItemPosition, int newItemPosition)– It decides whether two items have same data or not. This method is called by DiffUtil only if areItemsTheSame() returns true.
- getChangePayload(int oldItemPosition, int newItemPosition)– If areItemTheSame() returns true and areContentsTheSame() returns false then DiffUtil utility calls this method to get a payload about the change.
Getting Started
Below are a simple Student class which is using in the StudentRecyclerViewAdapter and StudentDiffCallback to sort the students list.
public class Student {
public int id;
public String name;
public String class;
}
Here is the implementation of Diff.Callback class. You can notice that getChangePayload() is not abstract method. This method is called when the areItemsTheSame() returns true, but areContentsTheSame() returns false, which means that we are talking about the same item but the fields data might have changed. Basically, this method returns the reason(s) why there is a difference in the lists.
public class StudentDiffCallback extends DiffUtil.Callback { private final List<Student> mOldStudentList;
private final List<Student> mNewStudentList;
public StudentDiffCallback(List<Student> oldStudentList, List<Student> newStudentList) {
this.mOldStudentList = oldStudentList;
this.mNewStudentList = newStudentList;
}@Override
public int getOldListSize() {
return mOldStudentList.size();
}@Override
public int getNewListSize() {
return mNewStudentList.size();
}@Override
public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
return mOldStudentList.get(oldItemPosition).getId() == mNewStudentList.get(newItemPosition).getId();
}@Override
public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
final Student oldStudentData = mOldStudentList.get(oldItemPosition);
final Student newStudentData = mNewStudentList.get(newItemPosition);
return oldStudentData.getName().equals(newStudentData.getName());
}@Nullable @Override
public Object getChangePayload(int oldItemPosition, int newItemPosition) {
return super.getChangePayload(oldItemPosition, newItemPosition);
}
}
After the DiffUtil.Callback implementation are done, we will update the list change in RecyclerViewAdapter .
public void updateList(ArrayList<Student> newList) { DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(new StudentDiffCallback(this.mStudentList, newList));
this.mStudentList.clear();
this.mStudentList.addAll(newList); diffResult.dispatchUpdatesTo(this);
}
We call dispatchUpdatesTo(this) method and adapter will be notified about the change.