ListAdapter is a RecyclerView adapter that displays a list. This is available in RecyclerView 27.1+, and the same function also exists in the AsyncListDiffer class if you cannot extend the adapter.

  • Operators on immutable lists
  • A simplified way to use DiffUtil
  • Provides animated updates
  • Concurrency support

ListAdapter helps you to work with RecyclerViews that change the content over time. All you need to do is submit a new list. It runs the DiffUtil tool behind the scenes for you on the background thread. Then it runs the animations based on how the list has changed. This is all handled via very simple API.

What you need to do is you create a DiffUtil callback. DiffUtil callback has to implement two methods. First one, make sure that the items are the same where you compare the item IDs. The second one you want to check the content is the same where you do a deeper comparison, essentially equals in Java. If there is a change, I’ll know how to crossfade your item from one to the next.

public class User {
    public static DiffUtil.ItemCallback<User> DIFF_CALLBACK = new  DiffUtil.ItemCallback<User>() {
        public boolean areItemsTheSame(@NonNull User oldItem, @NonNull User newItem) {
            return oldItem.userId == newItem.userId;

        public boolean areContentsTheSame(@NonNull User oldItem, @NonNull User newItem) {
            return oldItem.equals(newItem);
    public boolean equals(Object obj) {
        if (obj == this)
            return true;

        User user = (User) obj;

        return user.userId == this.userId && user.firstName == this.firstName;

The RecyclerView’s adapter needs to extend ListAdapter. onBind you just call getItem(), and you do your regular binding, and then that’s all you need to do to get the animation working.

public class UserAdapter extends ListAdapter<User, UserAdapter.UserItemViewHolder> {

    protected UserAdapter() {

    public UserItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
        View view = layoutInflater.inflate(R.layout.item_user_list, parent, false);
        return new UserItemViewHolder(view);

    public void onBindViewHolder(UserItemViewHolder holder, int position) {
        User user= getItem(position);
        if(user!=null) {

    static class UserItemViewHolder extends RecyclerView.ViewHolder {
        TextView userName, userId;

        public UserItemViewHolder(View itemView) {
            userId = itemView.findViewById(;
            userName = itemView.findViewById(;

        public void bindTo(User user) {

The simple code in the activity, you call submitList() and that’s it. This works really well with LiveData and RxJava observable.

 userAdapter = new UserAdapter();