DiffUtil это класс-утилита который может вычислять разницу между двумя списками и выводить список операций обновления, который конвертирует первый лист во второй. Это может использоваться для вычисления обновлений адаптера RecyclerView.В большинстве случаев наш список полностью меняется, и мы устанавливаем новый список в адаптер RecyclerView. И мы вызываем дорогостоящий notifyDataSetChanged для обновления адаптера. Класс DiffUtil решает эту проблему.
Давайте рассмотрим пример. Допустим, у нас есть список людей, в который мы добавляем случайные строки данных. Затем мы сортируем список по возрасту и обновляем RecyclerView.
Я собираюсь использовать статические данные для упрощения реализации.
public class DataProvider {
public static List
List
persons.add(new Person(1, 20, "John"));
persons.add(new Person(2, 12, "Jack"));
persons.add(new Person(3, 8, "Michael"));
persons.add(new Person(4, 19, "Rafael"));
return persons;
}
public static List
Collections.sort(oldList, new Comparator
@Override
public int compare(Person person, Person person2) {
return person.age - person2.age;
}
});
return oldList;
}
}
DiffUtil.Callback является абстрактным классом и имеет 4 абстрактных метода и 1 неабстрактный. Давайте их рассмотрим.
Методы DiffUtil.Callback
getOldListSize() : возвращает размер старого списка
getNewListSize() : возвращает размер нового списка
areItemsTheSame(int oldItemPosition, int newItemPosition) : Вызывается DiffUtil чтобы решить являются ли два объекта представлениями одного и того же элемента. Если ваши элементы содержат уникальные идентификаторы, этот метод должен проверить их равенство
areContentsTheSame(int oldItemPosition, int newItemPosition) : Проверяет содержат ли два элемента одинаковые данные. Вы можете изменить это поведение в зависимости от вашего UI. Этот метод вызывается DiffUtil только если areItemsTheSame возвращает true.
getChangePayload(int oldItemPosition, int newItemPosition) : Если areItemTheSame возвращает true и areContentsTheSame возвращает false, DiffUtil вызывает этот метод, чтобы получить информацию об изменениях. В моем примере я не использую изменяемые объекты, но если вы хотите это использовать, вы может посмотреть этот пример.
public class MyDiffCallback extends DiffUtil.Callback {
List
List
public MyDiffCallback(List
this.newPersons = newPersons;
this.oldPersons = oldPersons;
}
@Override
public int getOldListSize() {
return oldPersons.size();
}
@Override
public int getNewListSize() {
return newPersons.size();
}
@Override
public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
return oldPersons.get(oldItemPosition).id == newPersons.get(newItemPosition).id;
}
@Override
public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
return oldPersons.get(oldItemPosition).equals(newPersons.get(newItemPosition));
}
@Nullable
@Override
public Object getChangePayload(int oldItemPosition, int newItemPosition) {
// вы можете вернуть определенное поле для измененного элемента
return super.getChangePayload(oldItemPosition, newItemPosition);
}
}
Метод обновления данных в моем RecyclerViewAdapter
public void updateList(ArrayList
DiffUtil.DiffResult diffResult =
DiffUtil.calculateDiff(new MyDiffCallback(this.persons, newList));
diffResult.dispatchUpdatesTo(this);
}
Это все. Мы вызываем метод dispactUpdatesTo (RecyclerView.Adapter), и адаптер будет уведомлен об изменении.
Комментариев нет:
Отправить комментарий