2015-05-05 14 views
58

zu aktualisieren, wenn ich einen klassischen Adapter mit einem ListView verwenden müssen, ich meine Daten im Listview wie folgt aktualisiert:bester Weg, um Daten mit einem RecyclerView Adapter

myAdapter.swapArray(data); 

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

Ich mag würde wissen, was das Beste ist, üben für eine RecyclerView. Denn in einem RecyclerView Adapter können Sie keine clear und addAll wie in ListView tun.

So versuchte ich nur mit einem notifyDataSetChanged, aber es hat nicht funktioniert. Dann habe ich versucht, mit einem swapAdapter auf meiner Ansicht:

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

Aber mit dieser letzten Lösung, ich habe noch eine neue Instanz von meinem Adapter zu schaffen, und ich fühle mich wie es nicht die beste Lösung ist. Ich sollte nur in der Lage sein, meine Daten ohne eine neue MyRecyclerAdapter zu ändern.

+1

Es ist besser (für Animationen und Leistung), wenn Sie detaillierte Benachrichtigungsereignisse (z.notfiyItemInserted/Removed/Moved/Changed). Schauen Sie sich auch die SortedList-Klasse an, die diese Werte für Sie berechnen kann, wenn Sie ein Sortierkriterium in Ihrer Liste haben. – yigit

+0

Ich arbeite an jeder Änderung in meinem Adapter notifyDataSetChanged(); – marlonpya

Antwort

88

Der RecyclerView-Adapter verfügt nicht über viele Methoden, die sonst im ListView-Adapter verfügbar sind. Aber Ihre Swap kann ganz einfach implementiert werden, wie:

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

    public void swap(ArrayList<Data> datas) 
    { 
     if(datas == null || datas.size()==0) 
      return; 
     if (data != null && data.size()>0) 
      data.clear(); 
     data.addAll(datas); 
     notifyDataSetChanged(); 

    } 
} 

Auch gibt es einen Unterschied zwischen

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

und

list = newList; 

Die erste ist die gleiche Liste Objekt wiederverwendet. Der andere ist dereferenzierend und referenziert die Liste. Das alte Listenobjekt, das nicht mehr erreicht werden kann, wird als Garbage Collected erfasst, aber nicht ohne zuerst den Heapspeicher aufzustapeln. Dies wäre dasselbe wie die Initialisierung eines neuen Adapters, wenn Sie Daten austauschen möchten.

+0

Obwohl das obige für die einfache liste.size() funktioniert, war die Datenmenge von mir etwas komplex, wo ich mehrere Listen in der Recycleransicht habe. Die Recycler-Ansichtslistenansichten wurden von mehreren Ansichtsarten verwaltet. Daher war es schwierig, eine Teilmenge von Listenelementen zu entfernen, die von bindViewholder nicht sichtbar oder nicht bindbar sind. Der einzige Weg, der für mich funktioniert, ist RecyclerView.swapAdapter(); –

+0

Der oben erwähnte Austausch (ArrayList Daten) funktioniert nicht und weder die Log.d-Kommentarmethode RecyclerView.swapAdapter(); , habe sowieso meinen eigenen Weg gefunden, die Datenquelle (ArrayList am Erstellungsort) zu löschen, lösche als nächstes die Adapterdatenquelle mit Hilfe der Methode im Adapter und erstelle erneut eine neue Datenquelle (ArrayList) mit neuen Daten und dann diese Daten zur Adapterarrayliste und schließlich notifydatasetchanged() Methode. – blackjack

+0

@inmyth möglich Bearbeiten Sie in Ihrer Antwort oben: sollte "notifyDataSetChanged();" sei "data.notifyDataSetChanged();" ? – AJW

20

@ inmyths Antwort ist korrekt, ändern Sie einfach den Code ein wenig, um leere Liste zu behandeln.

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 Retrofit bin mit der Liste zu holen, auf Retrofit der onResponse() verwenden,

adapter.swap(feedList); 
3

Gefunden folgende Lösung für mein ähnliches Problem arbeiten:

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

die Klar- Verwendung Befehl

mData.clear() 

ist nicht notwendig

6

DiffUtil kann die beste Wahl für die Aktualisierung der Daten im RecyclerView Adapter, den Sie im Android-Framework finden können. DiffUtil ist eine Dienstprogrammklasse, die den Unterschied zwischen zwei Listen berechnen und eine Liste von Aktualisierungsoperationen ausgeben kann, die die erste in die zweite Liste konvertiert.

Die meiste Zeit ändert sich unsere Liste komplett und wir setzen neue Liste auf RecyclerView Adapter. Und wir rufen notifyDataSetChanged auf, um den Adapter zu aktualisieren. NotifyDataSetChanged ist teuer. Die DiffUtil-Klasse löst dieses Problem jetzt. Es macht seinen Job perfekt!

Verwandte Themen