web-dev-qa-db-ja.com

RecyclerViewアダプターでデータを更新する最良の方法

ListView で従来のアダプターを使用する必要がある場合、次のようにListViewのデータを更新します。

myAdapter.swapArray(data);

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

RecyclerView のベストプラクティスを教えてください。 RecyclerViewアダプターでは、ListViewのようにclearおよびaddAllを実行できないためです。

だから、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なしでデータを変更することができるはずです。

71
AlexDG

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;

1つ目は、同じリストオブジェクトを再利用することです。もう1つは、リストの逆参照と参照です。到達できなくなった古いリストオブジェクトは、ガベージコレクションされますが、最初にヒープメモリが蓄積されることはありません。これは、データを交換するたびに新しいアダプターを初期化するのと同じです。

105
inmyth

@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のonResponse()を使用して、Retrofitを使用してリストを取得しています。

adapter.swap(feedList);
21
Akshay Goyal

DiffUtil は、Androidフレームワークで見つけることができるRecyclerViewアダプターのデータを更新するための最良の選択です。 DiffUtilは、2つのリストの差を計算し、最初のリストを2番目のリストに変換する更新操作のリストを出力できるユーティリティクラスです。

ほとんどの場合、リストは完全に変更され、新しいリストをRecyclerView Adapterに設定します。そして、notifyDataSetChangedを呼び出してアダプターを更新します。 NotifyDataSetChangedはコストがかかります。 DiffUtilクラスはその問題を解決します。完璧に機能します!

10
Ngima Sherpa

私の同様の問題のために働いている次の解決策が見つかりました:

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

ネッセカリーではない

4
termigrator