Android AsyncListDiffer: RecyclerView’s Best Friend

Chao Shi
Chao Shi
Feb 14 · 3 min read
Design by Hannah Pratte

I think most Android developers are super familiar with RecyclerView, however you must also think of how to refresh the RecyclerView. In this tutorial, I will demonstrate an easy way on how to go about this process.

<Whole Refresh>

Adapter.notifyDataSetChanged();

This use to be the most common way to refresh the recyclerView, however its’ drawback are really obvious for two reasons:

  1. Refresh all the visible area on the recycleView, re-draw all the item. Not only this, if you have a bit more complex logic in your onBindViewHodler(), you will get stuck and lag.
  2. Cannot fire off the RecyclerView animation, which has a bad user experience.

<Partial Refresh>

To solve the problems mentioned above, RecyclerView has some partial refresh calls:

Adapter.notifyItemChanged(int)
Adapter.notifyItemInserted(int)
Adapter.notifyItemRangeChanged(int, int)
Adapter.notifyItemRangeInserted(int, int)
Adapter.notifyItemRangeRemoved(int, int)

This will give you a specific item/position to refresh. But, here comes the problem: What if you have a whole list? Do you have to calculate all the positions you need to refresh?

DiffUtil:

Google noticed this, and it published a Tool Class in support-recyclerview-v7:24 called DiffUtil.

DiffUtil.callback:

private DiffUtil.Callback diffCallback = new DiffUtil.Callback() {
@Override
public int getOldListSize() {
return oldList == null ? 0 : oldList.size();
}

Get DiffResult:

DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(diffCallback);

Set DiffResult to Adapter:

mAdapter.setData(newList);
diffResult.dispatchUpdatesTo(mAdapter);

Ok, since now we do not need notifyDataSetChanged() anymore, the performance of the refreshing can be improved. But, there are still some problems.

DiffUtil.calculateDiff() is running on the main thread, if we get a big size for a new list or old list, we are going to block the thread!

Solution: AsyncListDiff

Lets use some simple code to indicate how AsyncListDiff works:

public class UserAdapter extends RecyclerView.Adapter<UserAdapter.UserViewHolder> {
private AsyncListDiffer<User> mDiffer;//callBack
private DiffUtil.ItemCallback<User> diffCallback = new DiffUtil.ItemCallback<User>() {
@Override
public boolean areItemsTheSame(User oldItem, User newItem) {
return TextUtils.equals(oldItem.getId(), newItem.getId());
}

Here are the steps for using AsyncListDiffer:

Step 1: Create a DiffUtil.ItemCallback

Step 2: Let AsyncListDiffer to handle all the data

Step 3: Then what we are going to do is to use method submitList() to refresh the data/ui:

mAdapter.submitList(users);

As ever, QuarkWorks is available to help with any software application project — web, mobile, and more! If you are interested in our services you can check out our website. We would love to answer any questions you have! Just reach out to us on our Twitter, Facebook, or LinkedIn.

QuarkWorks, Inc.

Build better software.

Chao Shi

Written by

Chao Shi

Android developer

QuarkWorks, Inc.

Build better software.

More From Medium

More from QuarkWorks, Inc.

More from QuarkWorks, Inc.

Ruby on Rails: Active Record Enum

More from QuarkWorks, Inc.

More from QuarkWorks, Inc.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade