AsyncListDiffer
Helper for computing the difference between two lists via DiffUtil on a background thread.
It can be connected to a RecyclerView.Adapter, and will signal the adapter of changes between sumbitted lists.
For simplicity, the ListAdapter wrapper class can often be used instead of the AsyncListDiffer directly. This AsyncListDiffer can be used for complex cases, where overriding an adapter base class to support asynchronous List diffing isn't convenient.
The AsyncListDiffer can consume the values from a LiveData of List
and present the data simply for an adapter. It computes differences in list contents via DiffUtil on a background thread as new List
s are received.
Use getCurrentList to access the current List, and present its data objects. Diff results will be dispatched to the ListUpdateCallback immediately before the current list is updated. If you're dispatching list updates directly to an Adapter, this means the Adapter can safely access list items and total size via getCurrentList.
A complete usage pattern with Room would look like this:
@Dao
interface UserDao {
@Query("SELECT * FROM user ORDER BY lastName ASC")
public abstract LiveData<List<User>> usersByLastName();
}
class MyViewModel extends ViewModel {
public final LiveData<List<User>> usersList;
public MyViewModel(UserDao userDao) {
usersList = userDao.usersByLastName();
}
}
class MyActivity extends AppCompatActivity {
@Override
public void onCreate(Bundle savedState) {
super.onCreate(savedState);
MyViewModel viewModel = new ViewModelProvider(this).get(MyViewModel.class);
RecyclerView recyclerView = findViewById(R.id.user_list);
UserAdapter adapter = new UserAdapter();
viewModel.usersList.observe(this, list -> adapter.submitList(list));
recyclerView.setAdapter(adapter);
}
}
class UserAdapter extends RecyclerView.Adapter<UserViewHolder> {
private final AsyncListDiffer<User> mDiffer = new AsyncListDiffer(this, DIFF_CALLBACK);
@Override
public int getItemCount() {
return mDiffer.getCurrentList().size();
}
public void submitList(List<User> list) {
mDiffer.submitList(list);
}
@Override
public void onBindViewHolder(UserViewHolder holder, int position) {
User user = mDiffer.getCurrentList().get(position);
holder.bindTo(user);
}
public static final DiffUtil.ItemCallback<User> DIFF_CALLBACK
= new DiffUtil.ItemCallback<User>() {
@Override
public boolean areItemsTheSame(
@NonNull User oldUser, @NonNull User newUser) {
// User properties may have changed if reloaded from the DB, but ID is fixed
return oldUser.getId() == newUser.getId();
}
@Override
public boolean areContentsTheSame(
@NonNull User oldUser, @NonNull User newUser) {
// NOTE: if you use equals, your object must properly override Object#equals()
// Incorrectly returning false here will result in too many animations.
return oldUser.equals(newUser);
}
}
}
Parameters
Type of the lists this AsyncListDiffer will receive.
See also
Constructors
AsyncListDiffer(new AdapterListUpdateCallback(adapter),
new AsyncDifferConfig.Builder().setDiffCallback(diffCallback).build());