Best way to update data with a RecyclerView adapter

AndroidListviewAndroid RecyclerviewAndroid Adapter

Android Problem Overview


When I have to use a classic adapter with a ListView, I update my data in the ListView like this:

myAdapter.swapArray(data);

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

I would like to know what is the best practice for a RecyclerView. Because in a RecyclerView adapter you can't do a clear and addAll as in ListView.

So I tried just with a notifyDataSetChanged, but it didn't work. Then I tried with a swapAdapter on my view:

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);

But with this last solution, I still have to create a new instance of my adapter and I feel like it's not the best solution. I should be able just to change my data without a new MyRecyclerAdapter.

Android Solutions


Solution 1 - Android

RecyclerView's Adapter doesn't come with many methods otherwise available in ListView's adapter. But your swap can be implemented quite simply as:

class MyRecyclerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
   List<Data> data;
   ...
   
	public void swap(ArrayList<Data> datas)
	{
		data.clear();
		data.addAll(datas);
		notifyDataSetChanged();		
	}
}

Also there is a difference between

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

and

list = newList;

The first is reusing the same list object. The other is dereferencing and referencing the list. The old list object which can no longer be reached will be garbage collected but not without first piling up heap memory. This would be the same as initializing new adapter everytime you want to swap data.

Solution 2 - Android

@inmyth's answer is correct, just modify the code a bit, to handle empty list.

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();
    }

I am using Retrofit to fetch the list, on Retrofit's onResponse() use,

adapter.swap(feedList);

Solution 3 - Android

DiffUtil can the best choice for updating the data in the RecyclerView Adapter which you can find in the android framework. DiffUtil is a utility class that can calculate the difference between two lists and output a list of update operations that converts the first list into the second one.

Most of the time our list changes completely and we set new list to RecyclerView Adapter. And we call notifyDataSetChanged to update adapter. NotifyDataSetChanged is costly. DiffUtil class solves that problem now. It does its job perfectly!

Solution 4 - Android

Found following solution working for my similar problem:

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();
}

Using the clear-command

mData.clear()

is not nessescary

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAlex DGView Question on Stackoverflow
Solution 1 - AndroidinmythView Answer on Stackoverflow
Solution 2 - AndroidAkshay GoyalView Answer on Stackoverflow
Solution 3 - AndroidNgima SherpaView Answer on Stackoverflow
Solution 4 - AndroidtermigratorView Answer on Stackoverflow