Лучший способ обновления данных с помощью адаптера RecyclerView

Когда мне нужно использовать классический адаптер с ListView, я обновляю свои данные в ListView следующим образом:

myAdapter.swapArray(data);

public swapArray(List<Data> data) {
  clear();
  addAll(data);
  notifyDataSetChanged();
}

Я хотел бы знать, что лучше всего подходит для RecyclerView. Поскольку в адаптере RecyclerView вы не можете делать clear и addAll, как в ListView.

Итак, я попробовал только с notifyDataSetChanged, но это не сработало. Затем я попытался с swapAdapter на моем представлении:

List<Data> data = newData;

MyRecyclerAdapter adapter = new MyRecyclerAdapter(data);

// swapAdapter on my recyclerView (instead of a .setAdapter like with a classic listView).
recyclerViewList.swapAdapter(adapter, false);

Но с этим последним решением мне все еще нужно создать новый экземпляр моего адаптера, и я чувствую, что это не лучшее решение. Я мог бы просто изменить свои данные без нового MyRecyclerAdapter.

Ответ 1

Адаптер RecyclerView не имеет многих методов, доступных в адаптере ListView. Но ваш обмен может быть реализован довольно просто:

class MyRecyclerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
   List<Data> data;
   ...

    public void swap(ArrayList<Data> datas)
    {
        data.clear();
        data.addAll(datas);
        notifyDataSetChanged();     
    }
}

Также есть разница между

list.clear();
list.add(data);

а также

list = newList;

Первый - это повторное использование одного и того же объекта списка. Другой разыменование и ссылки на список. Старый объект списка, который больше не может быть достигнут, будет собираться мусором, но не без предварительного накопления кучи памяти. Это будет то же самое, что и инициализация нового адаптера каждый раз, когда вы хотите поменять местами данные.

Ответ 2

@inmyth ответ правильный, просто немного измените код, чтобы обрабатывать пустой список.

public class NewsAdapter extends RecyclerView.Adapter<...> {    
    ...
    private static List mFeedsList;
    ...    
    public void swap(List list){
            if (mFeedsList != null) {
                mFeedsList.clear();
                mFeedsList.addAll(list);
            }
            else {
                mFeedsList = list;
            }
            notifyDataSetChanged();
    }

Я использую Retrofit для извлечения списка, при использовании Retrofit onResponse(),

adapter.swap(feedList);

Ответ 3

DiffUtil может быть лучшим выбором для обновления данных в адаптере RecyclerView, который вы можете найти в платформе Android. DiffUtil - это служебный класс, который может вычислить разницу между двумя списками и вывести список операций обновления, которые преобразуют первый список во второй.

Большую часть времени наш список полностью меняется, и мы устанавливаем новый список в RecyclerView Adapter. И мы вызываем notifyDataSetChanged для обновления адаптера. NotifyDataSetChanged является дорогостоящим. Класс DiffUtil теперь решает эту проблему. Он отлично выполняет свою работу!

Ответ 4

Найдено следующее решение, работающее для моей аналогичной проблемы:

private ExtendedHashMap mData = new ExtendedHashMap();
private  String[] mKeys;

public void setNewData(ExtendedHashMap data) {
    mData.putAll(data);
    mKeys = data.keySet().toArray(new String[data.size()]);
    notifyDataSetChanged();
}

Использование команды clear-command

mData.clear()

не является обязательным