2014-10-29 16 views
34

Ich möchte Suchfunktionen für mein RecyclerView implementieren. Bei geändertem Text möchte ich die Daten ändern, die mit diesem Widget angezeigt werden. Vielleicht ist diese Frage vor gefragt worden, oder ist einfach, aber ich weiß nicht, wie die Änderung der Daten, die angezeigt werden soll ...RecyclerView Änderungsdatensatz

Meine RecyclerView wie folgt definiert ist:

 // 1. get a reference to recyclerView 
    mRecyclerView = (RecyclerView)findViewById(R.id.recyclerView); 

    // 2. set layoutManger 
    mRecyclerView.setLayoutManager(new LinearLayoutManager(this)); 
    // 3. create an adapter 
    mAdapter = new ItemsAdapter(itemsData); 
    // 4. set adapter 
    mRecyclerView.setAdapter(mAdapter); 

Und die Daten, die ich zeigen will, ist so etwas wie:

ItemData itemsData[] = { new ItemData("Mary Richards"), 
     new ItemData("Tom Brown"), 
     new ItemData("Lucy London")   
}; 

Also, wenn, wenn ich den Adapter einen anderen Satz von Daten geben wollen, ein weiteres Array (mit einem Element zum Beispiel), was soll ich tun?

+0

Wenn Sie ein anderes Array geben, möchten Sie einfach erstellen können neu 'ItemsAdapter' mit ihm und rufen' wieder setAdapter'. –

Antwort

74

Wenn Sie stabile IDs in Ihrem Adapter haben, können Sie ziemlich gute Ergebnisse (Animationen), wenn Sie ein neues Array erstellen, die gefilterten Elemente enthält und rufen

recyclerView.swapAdapter(newAdapter, false); 

Mit swapAdapter Hinweise RecyclerView, dass es View Holders erneut verwenden (vs in SetAdapter, muss es alle Ansichten recyceln und neu erstellen, da es nicht weiß, dass der neue Adapter den gleichen ViewHolder mit dem alten Adapter festgelegt hat).

Ein besserer Ansatz wäre, herauszufinden, welche Elemente entfernt werden und notifyItemRemoved(index) aufrufen. Vergessen Sie nicht, den Artikel tatsächlich zu entfernen. Dadurch kann RecyclerView prädiktive Animationen ausführen. Vorausgesetzt, dass Sie einen Adapter haben, die intern eine Arraylist verwendet, würde die Umsetzung wie folgt aussehen:

// adapter code 
final List<ItemData> mItems = new ArrayList(); //contains your items 
public void filterOut(String filter) { 
    final int size = mItems.size(); 
    for(int i = size - 1; i>= 0; i--) { 
     if (mItems.get(i).test(filter) == false) { 
      mItems.remove(i); 
      notifyItemRemoved(i); 
     } 
    } 
} 

Es wäre noch mehr leisten, wenn Sie können Batch notifyItemRemoved Anrufe und verwenden notifyItemRangeRemoved statt. Es würde aussehen etw wie: (nicht getestet)

public void filterOut(String filter) { 
    final int size = mItems.size(); 
    int batchCount = 0; // continuous # of items that are being removed 
    for(int i = size - 1; i>= 0; i--) { 
     if (mItems.get(i).test(filter) == false) { 
      mItems.remove(i); 
      batchCount ++; 
     } else if (batchCount != 0) { // dispatch batch 
      notifyItemRangeRemoved(i + 1, batchCount); 
      batchCount = 0; 
     } 
    } 
    // notify for remaining 
    if (batchCount != 0) { // dispatch remaining 
     notifyItemRangeRemoved(0, batchCount); 
    } 
} 

Sie müssen diesen Code erweitern Elemente hinzufügen, die zuvor herausgefiltert wurden, aber jetzt sollte sichtbar sein (zB Benutzer löscht die Filterabfrage), aber ich denke, das sollte man geben Sie die Grundidee.

Denken Sie daran, dass jeder Benachrichtigungs-Item-Aufruf die nachfolgenden betrifft (weshalb ich die Liste von Ende an durchquere, um sie zu vermeiden). Traversing from End hilft auch ArrayList beim Entfernen der Methodenleistung (weniger Elemente zum Verschieben).

Zum Beispiel, wenn Sie die Liste von Anfang an durchlaufen und die ersten beiden Elemente entfernen. Sie sollten entweder rufen

notifyItemRangeRemoved(0, 2); // 2 items starting from index 0 

oder wenn Sie ihnen ein Versand von einem

notifyItemRemoved(0); 
notifyItemRemoved(0);//because after the previous one is removed, this item is at position 0 
+0

Vielen Dank für Ihre Antwort, ich werde Anpassungen vornehmen, die meinen Bedürfnissen entsprechen, aber das ist, was ich im Grunde brauchte. Du hast es sehr gut erklärt. – Sandra

+1

Was bedeutet "stabile IDs"? Mein Datensatz ändert sich, aber ich weiß nicht, auf welche Art und Weise (einige neue Elemente können hinzugefügt werden und einige werden möglicherweise entfernt), aber die Ansicht bleibt gleich. Soll ich also true oder false an swapAdapter übergeben? –

2

einfach neu initialisieren Ihren Adapter:

mAdapter = new ItemsAdapter (newItemsData);

oder wenn Sie nur ein paar bestimmten Elemente eher als eine ganze Liste hinzufügen entfernen müssen:

mAdapter. notifyItemInserted (Position);

oder

mAdapter.notiftyItemRemoved (Position);

22

Dies ist meine Antwort - dank Ivan Skoric von seinem Standort: http://blog.lovelyhq.com/creating-lists-with-recyclerview-in-android/

habe ich eine zusätzliche Methode in meiner Adapterklasse:

public void updateList(List<Data> data) { 
    mData = data; 
    notifyDataSetChanged(); 
} 

Dann jedes Mal y Unsere Daten ändern sich, Sie rufen einfach diese Methode auf, geben Ihre neuen Daten ein und Ihre Ansicht sollte sich ändern, um sie widerzuspiegeln.

+0

notifyDataSetChanged() tötet alle Animationen, nur gut für große Listen. – Davidea

+0

@Davidea ... das ist der typische Anwendungsfall von RecyclerView –

+0

Eine Recycleransicht behält nur Ihre sichtbaren Ansichten im Speicher und gibt sie frei, wenn Sie sie von Ihrem Bildschirm scrollen. Es ist sehr effizient aus einer Speicherperspektive im Vergleich zu einer Listenansicht. Sie funktionieren ähnlich wie eine Listenansicht. Sie können die Recyclerview Dokumente hier lesen: https://developer.android.com/reference/android/support/v7/widget/RecyclerView.html – Simon

0

Als ygit beantwortet, ist interessant, wenn Sie den gesamten Inhalt ändern müssen.

Aber, in meinem FlexibleAdapter, können Sie die Elemente mit updateDataSet aktualisieren. Sie können den Adapter sogar so konfigurieren, dass er notifyDataSetChanged aufruft oder Synchronisierungsanimationen (standardmäßig aktiviert) hat. Das, weil notifyDataSetChanged alle Animationen abtötet, aber es ist gut für große Listen.

haben Sie einen Blick auf die Beschreibung, DemoApp und Wiki-Seiten: https://github.com/davideas/FlexibleAdapter