DiffUtil в Xamarin.Android - PullRequest
       8

DiffUtil в Xamarin.Android

0 голосов
/ 29 августа 2018

Младший разработчик здесь, пожалуйста, играйте хорошо :)

Мое приложение использует RecyclerView для отображения списка элементов, возвращаемых с сервера. Адаптер и обновление работают нормально, однако приложение временно зависает / зависает при обновлении / обновлении списка.

Я уверен, что когда он нажимает NotifyDataSetChanged (), он замерзает, поскольку это перерисовывает все в списке (в списке могут быть сотни элементов). После просмотра в Интернете выясняется, что DiffUtil может быть именно тем, что мне нужно, но я не могу найти какую-либо документацию или руководства для Xamarin.Android, просто обычный Android на основе Java, и я не понимаю ни одного языка, достаточного для его перевода.

Если кто-нибудь и направит меня в правильном направлении, это будет высоко оценено!

Ответы [ 2 ]

0 голосов
/ 17 сентября 2018

Мне удалось заставить 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), не обязательно должен быть внутри вашего адаптера, он может быть внутри вашей деятельности или фрагмента
0 голосов
/ 29 августа 2018

Это тоже довольно ново для меня, и я видел это раньше. Я попробовал буквально только сейчас, и через полчаса все заработало.

Итак, кое-что из этого пришло отсюда: https://medium.com/@iammert/using-diffutil-in-android-recyclerview-bdca8e4fbb00

И, в сущности, он говорит:

  1. Имеют 2 разные точки вашей структуры данных (List, IEnumerable и т. Д.), Похоже, у вас это уже есть, так что это хорошо.

  2. Имейте класс DiffUtil.Callback, в который вы будете передавать старые и новые данные, которые этот класс будет сравнивать друг с другом.

  3. Есть метод, который будет отправлять обновления вместе с вашим служебным классом. Хотя то, как он был опубликован, немного ошибочно, поскольку он не обновил старые данные. Но если ты это сделал, то это сработает так же, как и для меня.

Дайте мне знать, если у вас есть вопросы или возникнут проблемы.

...