Wie kann verhindert werden, dass das RecyclerView-Element nach “notifyItemChanged(pos)” blinkt?

Lesezeit: 5 Minuten

Ich habe derzeit eine Recycler-Ansicht, deren Daten alle 5 Sekunden aktualisiert werden. Um die Daten in der Liste zu aktualisieren, verwende ich

notifyItemChanged(position);
notifyItemRangeChanged(position, mList.size());

Jedes Mal, wenn ich notificationItemChanged() aufrufe, werden die Elemente in meiner Recycler-Ansicht ordnungsgemäß aktualisiert, sie blinkt jedoch, da dies dazu führt, dass onBindViewHolder erneut aufgerufen wird. Es ist also, als wäre es jedes Mal eine frische Ladung. Wie kann ich das ggf. verhindern?

  • Ich benutze Glide, um ein Bild zu laden, und versuche alle Antworten, um das Blinken zu lösen, aber es funktioniert nicht. dann mit Picasso das Problem lösen. und reibungslos laufen

    – Muklas

    9. August 2019 um 22:56 Uhr


  • Achten Sie auf dieses stackoverflow.com/a/32488059/1621111

    – Konstantin Konopko

    23. April 2021 um 14:56 Uhr

  • Bitte überprüfen Sie diesen Artikel: blog.undabot.com/…

    – Jewgen

    28. April 2021 um 13:54 Uhr

Benutzer-Avatar
Nick Cardoso

RecyclerView hat eingebaute Animationen, die normalerweise einen schönen polierten Effekt hinzufügen. In Ihrem Fall möchten Sie sie deaktivieren:

((SimpleItemAnimator) mRecyclerView.getItemAnimator()).setSupportsChangeAnimations(false);

(Der standardmäßige Recycler-Ansichtsanimator sollte bereits eine Instanz von sein SimpleItemAnimator)

Für Kotlin,

(mRecyclerView?.itemAnimator as SimpleItemAnimator).supportsChangeAnimations = false

  • ja! Das ist genau das, was ich brauchte.

    – Portfoliobuilder

    22. Februar 2017 um 0:17 Uhr

  • aber ich denke, dass dies auch Standardanimationen von Methoden wie “notifyItemInserted” deaktiviert

    Benutzer6650650

    22. Februar 2017 um 0:21 Uhr

  • @ user6650650 das funktioniert bei mir. Und du hast auch Recht. Vielen Dank!

    – Portfoliobuilder

    22. Februar 2017 um 0:29 Uhr

  • Worte toll für mich!!

    – Anfänger

    8. April 2020 um 4:43 Uhr

Sie können die Elementanimationen deaktivieren.

mRecyclerView.setItemAnimator(null);

  • Dies scheint Flickr nur schneller zu machen als zuvor, ich verwende Datenbindung. StableIds ist eine sinnvolle Optimierung, aber Sie haben immer noch ein flickr in den Zeilen, die aktualisiert werden (sie haben ein Optionsfeld, das den Status ändert, aber der Rest der Ansicht bleibt unverändert, also sollte filckr nicht verwendet werden).

    – hmac

    29. Oktober 2019 um 15:21 Uhr

  • Dies ist die beste Antwort. Ein paar Fehler auf einmal behoben.

    – Meister

    25. März 2021 um 2:13 Uhr

Das Problem kommt möglicherweise nicht von der Animation, sondern von nicht stabile ID des Listenelements.

Um stabile IDs zu verwenden, müssen Sie:

– setHasStableIds(true)
In RecyclerView.Adapter müssen wir setHasStableIds(true) setzen; true bedeutet, dass dieser Adapter einen eindeutigen Wert als Schlüssel für ein Element im Datensatz veröffentlichen würde. Der Adapter kann den Schlüssel verwenden, um anzugeben, dass es sich um denselben handelt oder nicht, nachdem die Daten geändert wurden.

– getItemId (int position) überschreiben
Dann müssen wir getItemId(int position) überschreiben, um den identifizierten Long-Wert für das Element an Position zurückzugeben. Wir müssen sicherstellen, dass es keine unterschiedlichen Artikeldaten mit derselben zurückgegebenen ID gibt.

Die Quelle der Lösung dafür ist hier.

  • Dies sollte die akzeptierte Antwort sein. setAnimator to null ist ein Hotfix und gilt nicht für diejenigen, die Animationen in ihrem RecyclerView @portfoliobuilder verwenden möchten

    – mochadwi

    20. Februar 2019 um 9:10 Uhr


  • Natürlich sollte es das, aber… Willkommen bei SO.

    – Marian Paździoch

    3. Februar 2021 um 11:31 Uhr


Verwenden Sie stableId in Ihrem Adapter.

Anruf adapter.setHasStableIds(true) und überschreiben getItemId(int position) -Methode in Ihrer Adapterklasse.

Geben Sie außerdem eine eindeutige ID von zurück getItemId(int position) für jeden Gegenstand. Bringen Sie nicht einfach die Position zurück.

Benutzer-Avatar
Rosuh

Wenn Sie die Animation von RecyclerView beibehalten und gleichzeitig das Aufblitzen von Gegenständen vermeiden möchten, können Sie die folgenden Schritte ausführen:

1. Status der Ansichtskomponente direkt ändern 2. Daten im Adapter direkt ändern 3. Die Benutzeroberfläche muss nicht manuell durch Aufrufen aktualisiert werden notifyItemChanged()

Nur die Ansicht direkt zu ändern, würde nicht sofort eine Änderung vornehmen, der bessere Weg ist die Verwendung payload es zu tun.

In deinem Adapter:

override fun onBindViewHolder(
        holder: RecyclerView.ViewHolder,
        position: Int,
        payloads: MutableList<Any>
    ) {
        // Using payload to refresh partly
        if (payloads.isNullOrEmpty()) {
            // refresh all 
            onBindViewHolder(holder, position)
            return
        }
        // just change one component's status which would not "flash".
        (holder as YourHolder).apply{
            // make you view change
            // etc. checkBox.isChecked = true
        }
    }

Und mit ihm:


yourAdapter.notifyItemChanged(position, "sample_pay_load")

Hier ist Doc

  • Gute Problemumgehung mit Payload als Hinweis darauf, ob die Aktualisierung teilweise erfolgt

    – A. Petrow

    15. Oktober 2021 um 14:40 Uhr

Benutzer-Avatar
tir38

Dies geschieht, weil Adapter neue ViewHolder erstellt und versucht, zwischen alten und neuen ViewHoldern zu animieren. Aus diesem Grund funktionieren alle Antworten zum Deaktivieren von Animationen technisch.

Stattdessen können Sie einfach sagen RecyclerView um Viewholders wiederzuverwenden canReuseUpdatedViewHolder(). Siehe diese Antwort auf eine ähnliche Frage: https://stackoverflow.com/a/60427676/1650674

  • Gute Problemumgehung mit Payload als Hinweis darauf, ob die Aktualisierung teilweise erfolgt

    – A. Petrow

    15. Oktober 2021 um 14:40 Uhr

Benutzer-Avatar
Karan vs

Ich habe die folgende Lösung gelesen und implementiert und sie funktioniert auf jedem Gerät, das ich getestet habe.

  • Klon Standard-Animatorklasse.
  • Kommentieren Sie in der Methode animateChange() unter 3 Zeilen,

    final float prevAlpha = oldHolder.itemView.getAlpha();
    .
    .
    oldHolder.itemView.setAlpha(prevAlpha);
    .
    .
    newHolder.itemView.setAlpha(0);
    
  • Stellen Sie den recyclerview item animator auf den Ihrer geklonten Klasse ein.

//Hinweis: Ich verstehe, wie die Lösung funktioniert, wenn der Alphawert des neuen Inhabers nicht geändert wird, aber dies ist nicht meine Lösung. Ich habe dies auf Stackoverflow selbst gelesen, konnte es aber aus irgendeinem Grund nicht mehr finden. Teilen Sie dies, um anderen Entwicklern zu helfen.

  • Ich denke, das ist eine der besten Antworten. Danke!

    – TootsieRockNRoll

    22. Juni 2020 um 21:44 Uhr

  • Entweder habe ich etwas falsch gemacht oder es funktioniert nicht. Ich habe verlängert DefaultItemAnimator() Klasse und überschrieben haben animateChange() aber das änderte nichts

    – Andreas

    15. Dezember 2020 um 15:30 Uhr

1256420cookie-checkWie kann verhindert werden, dass das RecyclerView-Element nach “notifyItemChanged(pos)” blinkt?

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

Privacy policy