notifyItemChanged(int)
notifyItemInserted(int)
notifyItemRemoved(int)
notifyItemRangeChanged(int, int)
notifyItemRangeInserted(int, int)
notifyItemRangeRemoved(int, int)
https://developer.android.com/reference/androidx/recyclerview/widget/RecyclerView.Adapter#notifyDataSetChanged()
- Eugene W. Myers의 difference 알고리즘을 이용해서 O(N + D^2)시간 안에 리스트의 비교를 수행
- N: 추가 및 제거된 항목의 갯수
- D: 스크립트의 길이
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
- 구현
- areItemsTheSame()
- areContentsTheSame()
https://developer.android.com/reference/androidx/recyclerview/widget/DiffUtil
- DiffUtil은 아이템 개수가 많을 경우 백그라운드 스레드에서 처리되어야 함
- DiffUtil에 대해 자체적으로 스레드 처리를 해주는 클래스
// Google Developers에서 제공하는 코드
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);
}
}
}
https://developer.android.com/reference/androidx/recyclerview/widget/AsyncListDiffer
- AsyncListDiffer를 더 쓰기 편하도록 랩핑한 클래스
- 리사이클러뷰 어댑터가 ListAdapter를 상속하게 하고 초기화시 DiffUtil 콜백 객체를 넘겨줌
- submitList()로 전체 데이터를 넘겨주면 어댑터가 백그라운드 스레드를 사용해 리스트 차이를 계산하여 화면을 갱신시켜줌
// Google Developers에서 제공하는 코드
class UserAdapter extends ListAdapter<User, UserViewHolder> {
public UserAdapter() {
super(User.DIFF_CALLBACK);
}
@Override
public void onBindViewHolder(UserViewHolder holder, int position) {
holder.bindTo(getItem(position));
}
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);
}
}
}
https://developer.android.com/reference/androidx/recyclerview/widget/ListAdapter