Мне удалось заставить DiffUtil работать в Xamarin.Android после прочтения этой статьи от VideoLAN: https://geoffreymetais.github.io/code/diffutil/. Он очень хорошо объясняет это, и примеры в его проекте очень полезны.
Ниже приведена «универсальная» версия моей реализации. Я бы порекомендовал прочитать о том, что делает каждый из вызовов override
, прежде чем реализовывать свой собственный обратный вызов (см. Ссылку выше). Поверьте, это помогает!
Обратный звонок:
using Android.Support.V7.Util;
using Newtonsoft.Json;
using System.Collections.Generic;
class YourCallback : DiffUtil.Callback
{
private List<YourItem> oldList;
private List<YourItem> newList;
public YourCallback(List<YourItem> oldList, List<YourItem> newList)
{
this.oldList = oldList;
this.newList = newList;
}
public override int OldListSize => oldList.Count;
public override int NewListSize => newList.Count;
public override bool AreItemsTheSame(int oldItemPosition, int newItemPosition)
{
return oldList[oldItemPosition].Id == newList[newItemPosition].Id;
}
public override bool AreContentsTheSame(int oldItemPosition, int newItemPosition)
{
// Using JsonConvert is an easy way to compare the full contents of a data model however, you can check individual components as well
return JsonConvert.SerializeObject(oldList[oldItemPosition]).Equals(JsonConvert.SerializeObject(newList[newItemPosition]));
}
}
Вместо вызова NotifyDataSetChanged()
выполните следующее:
private List<YourItem> items = new List<YourItem>();
private void AddItems()
{
// Instead of adding new items straight to the main list, create a second list
List<YourItem> newItems = new List<YourItem>();
newItems.AddRange(items);
newItems.Add(newItem);
// Set detectMoves to true for smoother animations
DiffUtil.DiffResult result = DiffUtil.CalculateDiff(new YourCallback(items, newItems), true);
// Overwrite the old data
items.Clear();
items.AddRange(newItems);
// Despatch the updates to your RecyclerAdapter
result.DispatchUpdatesTo(yourRecyclerAdapter);
}
Можно оптимизировать его еще больше, используя пользовательские полезные нагрузки и т. Д., Но это уже на голову выше вызова NotifyDataSetChanged()
на вашем адаптере.
Последние несколько вещей, которые я потратил, пытаясь найти в Интернете:
- DiffUtil работает во фрагментах
- DiffUtil может обновлять пустой список (т. Е. Предварительно не требуются данные)
- Анимации обрабатываются системой (т.е. вам не нужно добавлять их самостоятельно)
- Метод, который вызывает
DispatchUpdatesTo(yourRecyclerAdapter)
, не обязательно должен быть внутри вашего адаптера, он может быть внутри вашей деятельности или фрагмента