web-dev-qa-db-fra.com

Meilleure façon de mettre à jour les données avec un adaptateur RecyclerView

Lorsque je dois utiliser un adaptateur classique avec un ListView , je mets à jour mes données dans ListView de la manière suivante:

myAdapter.swapArray(data);

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

Je voudrais savoir quelle est la meilleure pratique pour un RecyclerView . Parce que dans un adaptateur RecyclerView , vous ne pouvez pas effectuer de clear et addAll comme dans ListView .

Alors j'ai juste essayé avec un notifyDataSetChanged, mais cela n'a pas fonctionné. Puis j'ai essayé avec un swapAdapter de ma vue:

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

Mais avec cette dernière solution, je dois toujours créer une nouvelle instance de mon adaptateur et je sens que ce n'est pas la meilleure solution. Je devrais pouvoir changer mes données sans un nouveau MyRecyclerAdapter.

71
AlexDG

L’adaptateur de RecyclerView n’est pas livré avec de nombreuses méthodes que l’adaptateur de ListView ne propose pas. Mais votre échange peut être implémenté tout simplement comme:

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

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

Il y a aussi une différence entre

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

et

list = newList;

Le premier est de réutiliser le même objet de liste. L'autre consiste à déréférencer et à référencer la liste. Les anciens objets de la liste qui ne peuvent plus être atteints seront récupérés, mais pas avant d’empiler d’abord de la mémoire. Cela équivaudrait à initialiser un nouvel adaptateur à chaque fois que vous souhaitez échanger des données.

105
inmyth

La réponse de @ inmyth est correcte, il suffit de modifier un peu le code pour gérer une liste vide.

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

J'utilise Retrofit pour récupérer la liste, à l'usage de Retrofit onResponse (),

adapter.swap(feedList);
21
Akshay Goyal

DiffUtil constitue le meilleur choix pour la mise à jour des données dans l'adaptateur RecyclerView que vous pouvez trouver dans le cadre Android. DiffUtil est une classe utilitaire qui peut calculer la différence entre deux listes et générer une liste d'opérations de mise à jour qui convertit la première liste en une seconde.

La plupart du temps, notre liste change complètement et nous définissons une nouvelle liste sur RecyclerView Adapter. Et nous appelons notifyDataSetChanged pour mettre à jour l'adaptateur. NotifyDataSetChanged est coûteux. La classe DiffUtil résout ce problème maintenant. Il fait parfaitement son travail!

11
Ngima Sherpa

J'ai trouvé la solution suivante fonctionnant pour mon problème similaire:

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

Utiliser la commande claire

mData.clear()

n'est pas nessescary

4
termigrator