RecyclerView – alle vorhandenen Views/Viewholder abrufen

Lesezeit: 9 Minuten

Ich möchte die aktualisieren RecyclerView Während es Daten anzeigt, zeige ich in meinem Fall Bilder mit oder ohne Beschriftungen.

Standardmäßig lege ich die Sichtbarkeit der Beschriftung fest, wenn ich den Ansichtshalter erstelle, und das ist in Ordnung, aber ich möchte, dass der Benutzer die Sichtbarkeit der Beschriftung über das Menü ändert, während die RecyclerView angezeigt wird, daher möchte ich die Sichtbarkeit für alle vorhandenen Ansichten in der manuell aktualisieren RecyclerView.

Kann ich irgendwie alle vorhandenen bekommen Views? Ich brauche alle, nicht nur die sichtbaren, die möchte ich später nicht wiederverwerten View wird nicht aktualisiert…

  • Haben Sie Parameter, um zu wissen, ob das Label im onBindViewHolder sichtbar ist oder nicht? Sie sollten diesen Parameter überprüfen. Aktualisieren Sie den Parameter im Menü und setzen Sie adapter.notifyDataSetChanged

    – Chol

    12. Januar 2016 um 11:20 Uhr


  • Ich lese aus den Einstellungen, also möchte ich das EINMAL machen und nicht immer … Ich könnte es auch mit einem internen booleschen Wert im Adapter machen, habe eigentlich nicht daran gedacht …

    – Abschlussball85

    12. Januar 2016 um 11:22 Uhr

  • Ist dieser Parameter für alle Artikel gleich? oder kann je nach Artikel unterschiedlich sein?

    – Chol

    12. Januar 2016 um 11:23 Uhr

  • Für alle gleich … Deshalb würde ich es vorziehen, über alle vorhandenen Ansichten zu iterieren …

    – Abschlussball85

    12. Januar 2016 um 11:25 Uhr

  • Sie können diesen Wert an den Adapterkonstruktor übergeben und eine Methode in Adapter erstellen, um diesen Wert zu ändern

    – Chol

    12. Januar 2016 um 11:27 Uhr

Benutzeravatar des Android-Entwicklers
Android-Entwickler

Zuerst müssen Sie alle angezeigten Indizes der Ansichten abrufen, und dann müssen Sie jeden durchgehen und den viewHolder jeder Ansicht verwenden:

final int firstVisibleItemPosition = layoutManager.findFirstVisibleItemPosition();
final int lastVisibleItemPosition = layoutManager.findLastVisibleItemPosition();
for (int i = firstVisibleItemPosition; i <= lastVisibleItemPosition; ++i) {
    ViewHolder holder = (ViewHolder) mRecyclerView.findViewHolderForAdapterPosition(i);
    ...
    }

BEARBEITEN: Es scheint, dass nicht immer alle ViewHolder zurückgegeben werden, die Sie möglicherweise behandeln möchten. Dies scheint eine stabilere Lösung zu sein:

for (int childCount = recyclerView.getChildCount(), i = 0; i < childCount; ++i) {
   final ViewHolder holder = recyclerView.getChildViewHolder(recyclerView.getChildAt(i));
   ...
   }

Hinweis: In einigen Fällen möchten Sie möglicherweise die Anzahl der zwischengespeicherten Ansichten so einstellen, dass sie groß genug ist, damit Sie immer die gleichen Ansichten wiederverwerten, anstatt neue. Dafür können Sie so etwas verwenden:

fun RecyclerView.setMaxViewPoolSize(maxViewTypeId: Int, maxPoolSize: Int) {
    for (i in 0..maxViewTypeId)
        recycledViewPool.setMaxRecycledViews(i, maxPoolSize)
}

Beispielnutzung:

recyclerView.setMaxViewPoolSize(MAX_TYPE_ITEM, Int.MAX_VALUE)

  • Dies ist die richtige Antwort auf die Frage “alle vorhandenen Views/Viewholder abrufen” und genau das, was ich brauchte. Danke vielmals!

    – Albert Vila Calvo

    13. Mai 2016 um 14:06 Uhr

  • @JasonTyler Um eine RecyclerView zu verwenden, erstellen Sie immer eine LayoutManager-Instanz, also haben Sie sie vorher. Hier ist eine Möglichkeit, es zu erstellen, um wie eine vertikale Liste zu arbeiten (aber auch hier müssen Sie auswählen, welche Sie verwenden möchten): LayoutManager layoutManager=new LinearLayoutManager(this,LinearLayoutManager.VERTICAL,false)

    – Android-Entwickler

    6. Oktober 2016 um 5:45 Uhr

  • Das ist auch nicht richtig, es gibt gebundene Viewholder, die noch nicht sichtbar sind: Nach dem Laden beim Start sind normalerweise 2 oder 3 Items über die letzte sichtbare Position gebunden.

    – Davideas

    18. Dezember 2016 um 17:45 Uhr

  • @androiddeveloper, ich habe gerade experimentiert und die Protokolle beobachtet, die ich eingefügt habe, dass es mehr Elemente bindet, die nicht sichtbar sind. Tatsächlich habe ich keine Möglichkeit gefunden, sie abzurufen. Am Ende habe ich sie in einem Satz zwischengespeichert oder diese aufgelistet ViewHolders in onBindViewHolder() und um sie zu entcachen onViewRecycled()

    – Davideas

    20. Dezember 2016 um 15:51 Uhr

  • Ich kann bestätigen, dass die Feststellung von @Davidea richtig ist. Es gibt mehr gecachte Ansichtshalter als (lastVisibleItemPosition – firstVisibleItemPosition + 1)

    – Cheok Yan Cheng

    8. Juni 2017 um 11:23 Uhr

Benutzeravatar von Davideas
Davideas

  • Aktualisieren der gesamten Adapterlistengröße mit notifyDataSetChanged() ist nicht bequem.
  • Es reicht nicht aus, alle aktuellen untergeordneten RecyclerView-Objekte (dh alle sichtbaren Elemente) zu erhalten: Es gibt gebundene Ansichtshalter, die nicht sichtbar sind: Nach dem Laden beim Start sind normalerweise 2 oder 3 Elemente über der letzten sichtbaren Position gebunden (abhängig von Ihrem LayoutManager). .

Ich habe gerade experimentiert, indem ich die von mir abgelegten Protokolle beobachtet habe, dass RV mehr Elemente bindet, die nicht sichtbar sind, tatsächlich habe ich keine Möglichkeit gefunden, sie abzurufen. Ich landete bei Zwischenspeicher in einem Set oder List diese ViewHolder in onBindViewHolder() und zu entcachen sie hinein onViewRecycled():

private Set<AbstractViewHolder> mBoundViewHolders = new HashSet<>();
private int mVisibility = View.VISIBILE;

// So you can have access from the Activity/Fragment
public Set<AbstractViewHolder> getAllBoundViewHolders() {
    return Collections.unmodifiableSet(mBoundViewHolders);
}

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position, List payloads) {
    // Binding code
    ...
    holder.view.setVisibility(mVisibility);

    // Caching VH
    mBoundViewHolders.add((AbstractViewHolder) holder);
}

@Override
public void onViewRecycled(RecyclerView.ViewHolder holder) {
    // Uncaching VH
    mBoundViewHolders.remove(holder);
}

// Your method becomes
public void updateVisibility(int visibility) {
    mVisibility = visibility;
    for (AbstractViewHolder holder : mBoundViewHolders) {
        holder.updateVisibility(visibility);
    }
}

Implementieren Sie Ihre Schnittstelle oder Ihren abstrakten ViewHolder, damit Sie Ihre Methode aufrufen können. Auf diese Weise haben Sie Zugriff auf Ihre ViewHolder-Inhalte.


Das mache ich in meinem FlexibleAdapter um die Elemente abzuwählen ohne unter Berufung auf die notifyItemRangeChanged(). Und wenn der Benutzer Animationen hat, werden alle ausgeführt, und der Hintergrund ändert sich auch, wenn ich meine Methode aufrufe toggleActivation().

Wenn Sie einen besseren Weg kennen, um alle gebundenen VH abzurufen, lassen Sie es mich wissen.

  • Was würde passieren, wenn ich anstelle von Hinzufügen und Entfernen in das Set einfach alle ViewHolder in onCreateViewHolder speichern würde?

    – Android-Entwickler

    27. Dezember 2016 um 17:32 Uhr

  • @androiddeveloper In meiner Bibliothek kann es nicht funktionieren, da die VH noch nicht erstellt wurde. Aber Sie können versuchen, zu sehen, was in Ihrem Adapter passiert.

    – Davideas

    27. Dezember 2016 um 22:43 Uhr


  • @Davidea Ich habe dir diese Antwort noch nie gegeben! Guter Workaround, Mann!

    – Srujan Barai

    25. Januar 2017 um 2:51 Uhr

  • Ist es besser, VH zu speichern, mit WeakReference ?

    – Cheok Yan Cheng

    8. Juni 2017 um 11:28 Uhr

  • Darf ich empfehlen, diese Datenstruktur zu verwenden, um zwischengespeicherte VH zu speichern – Set<AbstractViewHolder> mBoundViewHolders = Collections.newSetFromMap(new java.util.WeakHashMap<AbstractViewHolder, Boolean>());

    – Cheok Yan Cheng

    8. Juni 2017 um 15:56 Uhr

Chols Benutzeravatar
Chol

In der Adapterklasse:

Boolean isVisible = false;

public CustomAdapter(boolean isVisible) {
    this.isVisible= isVisible;
}
    @Override
    public void onBindViewHolder(ViewHolder holder, final int position) {
     ...

         if (isVisible){
           //setVisibility(View.VISIBLE)
         }else{
         //setVisibility(View.INVISIBLE
         }
    }

public void updateVisibility(boolean newValue){
 isVisible= newValue;
}

In Activity wo Sie den Wert aktualisieren möchten, wo der Adapter instanziiert wird:

adapter.updateVisibility(false);
adapter.notifydataSetChanged();

  • In updateVisibility musst du hinzufügen notifyDataSetChanged() aber dann funktioniert das und das ist meine aktuelle Lösung … Trotzdem scheint es mir nicht perfekt zu sein, der Benutzer ändert die Sichtbarkeit sehr selten, während er fast immer scrollt, also ist das ständige Einstellen der Sichtbarkeit nicht die effektivste Lösung für mich …

    – Abschlussball85

    12. Januar 2016 um 11:34 Uhr

  • @ prom85, innerhalb der View-Klasse gibt es einige Überprüfungen, ob die Sichtbarkeit geändert wurde, also wenn Sie anrufen setVisibility mit dem gleichen Wert ist es kein Problem.

    – Dilix

    12. Januar 2016 um 11:38 Uhr

  • Meine Tests zeigen, dass prom85 recht hat: I tun muss anrufen notifyDataSetChanged() um die RecyclerView zu zwingen, die Änderungen in Elementen neu zu zeichnen, die bereits angezeigt werden, aber geändert werden müssen.

    – SMBiggs

    13. Oktober 2016 um 5:59 Uhr

  • Sehr dankbar für Sie

    – Schamsul Arefin

    10. Januar 2018 um 12:52 Uhr

  • Diese Lösung ist die beste Lösung auf dieser Seite, da sie die einzige ist, die die Sichtbarkeit für alle Recyclerview-Elemente aktualisiert – einschließlich derer, die noch nicht gescrollt wurden!

    – M.Marmor

    12. Juli 2018 um 20:25 Uhr

Alle vorhandenen Ansichten sind sichtbar, plus einige Ansichten, die von zwischengespeichert wurden RecyclerView. Sie können auf alle sichtbaren zugreifen Viewist so:

View child;
for (int i = 0; i < mRecycler.getChildCount(); i++) {
    child = mRecycler.getChildAt(i);
    //In case you need to access ViewHolder:
    mRecycler.getChildViewHolder(child);
}

Auch wenn Sie auf cached zugreifen ViewDa sie noch nicht an Daten gebunden sind, wissen Sie nicht, ob das Label sichtbar sein soll oder nicht. Stellen Sie einfach die Sichtbarkeit der Etiketten auf verbleibend ein Views in onBindViewHolder.

Der Rest des Views existiert einfach noch nicht, also können Sie nichts daran ändern, selbst wenn es für alle denselben Label-Sichtbarkeitsstatus gibt.

Benutzeravatar von Srujan Barai
Srujan Barai

Alle oben genannten Lösungen geben nur die sichtbaren Halter an, aber in Wirklichkeit gibt es 2-3 andere Halter, die gebunden, aber nicht sichtbar sind. Um auch diese zu bekommen, ist der einfachste und genaueste Weg, den ich mir vorstellen kann, um alle Halter zu bekommen:

int lastBoundHolderPosition = -1;
int lastDetachedHolderPosition = -1;

public void onBindViewHolder(final MyViewHolder holder, int position) {
    lastBoundHolderPosition = position;
    //Your implementation
}
public void onViewDetachedFromWindow(MyViewHolder holder){
    lastDetachedHolderPosition = holder.holder.getAdapterPosition();
}

Wenn Sie möchten, dass alle Adapter sichtbar sind (plus Gebunden, aber nicht sichtbar):

if(lastDetachedHolderPosition == -1){
    for(pos = 0; pos <= lastDetachedHolderPosition; pos++){
        ViewHolder holder = (ViewHolder) mRecyclerView.findViewHolderForAdapterPosition(pos);
    }
}else{
    if(lastBoundHolderPosition > lastDetachedHolderPosition){ //Scroll down
        //get all the bound holders
        for(int pos = lastDetachedHolderPosition + 1; pos <= lastBoundHolderPosition; pos++){
            ViewHolder holder = (ViewHolder) mRecyclerView.findViewHolderForAdapterPosition(pos);
        }
    }else{ //Scroll up
        //get all the bound holders
        for(int pos = lastBoundHolderPosition ; pos <= lastDetachedHolderPosition-1; pos++){
            ViewHolder holder = (ViewHolder) mRecyclerView.findViewHolderForAdapterPosition(pos);
        }

    }
}

  • Was ist mit dem Abrufen der Viewholder, wenn nicht gescrollt wird? Zum Beispiel, nachdem auf die Schaltfläche geklickt wurde?

    – Android-Entwickler

    23. Januar 2017 um 13:46 Uhr

  • hmmm … Ein anderer ähnlicher Ansatz wäre, ein Set von ViewHolders zu haben, und dies vermeidet auch den Aufruf von “findViewHolderForAdapterPosition” . Kann kürzer sein und könnte ein kleines bisschen effektiver sein. Nein ?

    – Android-Entwickler

    23. Januar 2017 um 23:32 Uhr

  • Wir wollen nur die aktuell gebundenen VH, die einzige Möglichkeit besteht darin, zu überwachen, wann sie recycelt (= ungebunden) werden, was die von mir vorgeschlagene Lösung ist! onViewDetachedFromWindow() wird aufgerufen, wenn VH nicht sichtbar ist, aber noch gebunden ist, also nicht präzise genug ist.

    – Davideas

    24. Januar 2017 um 14:32 Uhr


  • Erste Bedingung macht keinen Sinn. Sie prüfen ggf lastDetachedHolderPosition==-1 , und wenn ja, gehe von 0 zu ihr, was bedeutet, von 0 nach -1 . Es bedeutet, dass die Schleife niemals etwas tun wird.

    – Android-Entwickler

    29. Januar 2018 um 12:45 Uhr

  • Was ist mit dem Abrufen der Viewholder, wenn nicht gescrollt wird? Zum Beispiel, nachdem auf die Schaltfläche geklickt wurde?

    – Android-Entwickler

    23. Januar 2017 um 13:46 Uhr

  • hmmm … Ein anderer ähnlicher Ansatz wäre, ein Set von ViewHolders zu haben, und dies vermeidet auch den Aufruf von “findViewHolderForAdapterPosition” . Kann kürzer sein und könnte ein kleines bisschen effektiver sein. Nein ?

    – Android-Entwickler

    23. Januar 2017 um 23:32 Uhr

  • Wir wollen nur die aktuell gebundenen VH, die einzige Möglichkeit besteht darin, zu überwachen, wann sie recycelt (= ungebunden) werden, was die von mir vorgeschlagene Lösung ist! onViewDetachedFromWindow() wird aufgerufen, wenn VH nicht sichtbar ist, aber noch gebunden ist, also nicht präzise genug ist.

    – Davideas

    24. Januar 2017 um 14:32 Uhr


  • Erste Bedingung macht keinen Sinn. Sie prüfen ggf lastDetachedHolderPosition==-1 , und wenn ja, gehe von 0 zu ihr, was bedeutet, von 0 nach -1 . Es bedeutet, dass die Schleife niemals etwas tun wird.

    – Android-Entwickler

    29. Januar 2018 um 12:45 Uhr

1438680cookie-checkRecyclerView – alle vorhandenen Views/Viewholder abrufen

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy