Ich habe eine RecyclerView, die einige Daten von der API lädt, eine Bild-URL und einige Daten enthält, und ich verwende networkImageView, um das Bild verzögert zu laden.
@Override
public void onResponse(List<Item> response) {
mItems.clear();
for (Item item : response) {
mItems.add(item);
}
mAdapter.notifyDataSetChanged();
mSwipeRefreshLayout.setRefreshing(false);
}
Hier ist die Implementierung für Adapter:
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, final int position) {
if (isHeader(position)) {
return;
}
// - get element from your dataset at this position
// - replace the contents of the view with that element
MyViewHolder holder = (MyViewHolder) viewHolder;
final Item item = mItems.get(position - 1); // Subtract 1 for header
holder.title.setText(item.getTitle());
holder.image.setImageUrl(item.getImg_url(), VolleyClient.getInstance(mCtx).getImageLoader());
holder.image.setErrorImageResId(android.R.drawable.ic_dialog_alert);
holder.origin.setText(item.getOrigin());
}
Das Problem ist, wenn wir in der recyclerView eine Aktualisierung haben, blinkt sie am Anfang für eine sehr kurze Zeit, was seltsam aussieht.
Ich habe stattdessen nur GridView / ListView verwendet und es hat wie erwartet funktioniert. Es gab kein Blinzeln.
Konfiguration für RecycleView in onViewCreated of my Fragment
:
mRecyclerView = (RecyclerView) view.findViewById(R.id.recyclerView);
// use this setting to improve performance if you know that changes
// in content do not change the layout size of the RecyclerView
mRecyclerView.setHasFixedSize(true);
mGridLayoutManager = (GridLayoutManager) mRecyclerView.getLayoutManager();
mGridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
@Override
public int getSpanSize(int position) {
return mAdapter.isHeader(position) ? mGridLayoutManager.getSpanCount() : 1;
}
});
mRecyclerView.setAdapter(mAdapter);
Hat jemand ein solches Problem? Was könnte der Grund sein?
Antworten:
Versuchen Sie, stabile IDs in Ihrem RecyclerView.Adapter zu verwenden
setHasStableIds(true)
und überschreibengetItemId(int position)
.Ohne stabile IDs werden
notifyDataSetChanged()
ViewHolders danach normalerweise nicht denselben Positionen zugewiesen. Das war in meinem Fall der Grund zu blinken.Eine gute Erklärung finden Sie hier.
quelle
Laut dieser Problemseite ... ist dies die Standardanimation zum Ändern von Recyclingview-Elementen ... Sie können sie deaktivieren ... versuchen Sie dies
Änderung in der neuesten Version
Zitiert aus dem Android-Entwicklerblog :
quelle
Das hat einfach funktioniert:
quelle
code
ItemAnimator animator = recyclerView.getItemAnimator (); if (Animatorinstanz von SimpleItemAnimator) {((SimpleItemAnimator) Animator) .setSupportsChangeAnimations (false); }code
Ich habe das gleiche Problem beim Laden des Bildes von einigen URLs und dann blinkt imageView. Gelöst mit
anstatt
Dadurch wird vermieden, dass diese unveränderten alten Daten neu geladen werden.
quelle
Versuchen Sie dies, um die Standardanimation zu deaktivieren
Dies ist die neue Möglichkeit, die Animation zu deaktivieren, da Android 23 unterstützt
Diese alte Methode funktioniert für ältere Versionen der Support-Bibliothek
quelle
Angenommen,
mItems
die Sammlung unterstützt SieAdapter
. Warum entfernen Sie alles und fügen es erneut hinzu? Sie sagen im Grunde, dass sich alles geändert hat, sodass RecyclerView alle Ansichten neu bindet, als ich annehme, dass die Bildbibliothek nicht richtig damit umgeht, wenn die Ansicht immer noch zurückgesetzt wird, obwohl es sich um dieselbe Bild-URL handelt. Vielleicht hatten sie eine Lösung für AdapterView eingebrannt, damit es in GridView gut funktioniert.Anstatt aufzurufen,
notifyDataSetChanged
wodurch alle Ansichten erneut gebunden werden, rufen Sie granulare Benachrichtigungsereignisse auf (Benachrichtigung hinzugefügt / entfernt / verschoben / aktualisiert), damit RecyclerView nur die erforderlichen Ansichten neu bindet und nichts flackert.quelle
Recyclerview verwendet DefaultItemAnimator als Standardanimator. Wie Sie dem folgenden Code entnehmen können, ändern sie das Alpha des Ansichtsinhabers beim Ändern des Elements:
Ich wollte den Rest der Animationen beibehalten, aber das "Flimmern" entfernen, also habe ich DefaultItemAnimator geklont und die 3 Alpha-Linien oben entfernt.
Um den neuen Animator zu verwenden, rufen Sie einfach setItemAnimator () in Ihrer RecyclerView auf:
quelle
In Kotlin können Sie die Klassenerweiterung für RecyclerView verwenden:
quelle
Hey @Ali, es könnte eine späte Wiederholung sein. Ich habe mich auch diesem Problem gestellt und es mit der folgenden Lösung gelöst. Es kann Ihnen helfen, dies zu überprüfen.
Die LruBitmapCache.java- Klasse wird erstellt, um die Größe des Bildcaches zu ermitteln
Die VolleyClient.java- Singleton-Klasse [erweitert die Anwendung] wurde unter dem Code hinzugefügt
Fügen Sie im VolleyClient-Singleton-Klassenkonstruktor das folgende Snippet hinzu, um den ImageLoader zu initialisieren
Ich habe die Methode getLruBitmapCache () erstellt, um LruBitmapCache zurückzugeben
Hoffe, es wird dir helfen.
quelle
für mich hat
recyclerView.setHasFixedSize(true);
gearbeitetquelle
In meinem Fall funktionierten weder die oben genannten noch die Antworten von anderen Stackoverflow-Fragen mit denselben Problemen.
Nun, ich habe jedes Mal, wenn auf das Element geklickt wird, eine benutzerdefinierte Animation verwendet, für die ich notifyItemChanged (int position, Object Payload) aufgerufen habe, um die Nutzdaten an meine CustomAnimator-Klasse zu übergeben.
Beachten Sie, dass im RecyclerView-Adapter zwei onBindViewHolder-Methoden (...) verfügbar sind. Die Methode onBindViewHolder (...) mit 3 Parametern wird immer vor der Methode onBindViewHolder (...) mit 2 Parametern aufgerufen.
Im Allgemeinen überschreiben wir immer die onBindViewHolder (...) -Methode mit 2 Parametern und die Hauptursache des Problems war, dass ich dasselbe tat, da jedes Mal, wenn notifyItemChanged (...) aufgerufen wird, unsere onBindViewHolder (...) -Methode ausgeführt wird aufgerufen werden, in dem ich mein Bild mit Picasso in ImageView geladen habe, und dies war der Grund, warum es erneut geladen wurde, unabhängig davon, ob es aus dem Speicher oder aus dem Internet stammt. Bis zum Laden wurde mir das Platzhalterbild angezeigt. Dies war der Grund, warum ich 1 Sekunde lang blinkte, wenn ich auf die Elementansicht klickte.
Später überschreibe ich auch eine andere onBindViewHolder (...) -Methode mit 3 Parametern. Hier überprüfe ich, ob die Liste der Nutzdaten leer ist, und gebe dann die Super-Klassen-Implementierung dieser Methode zurück. Wenn es Nutzdaten gibt, setze ich nur den Alpha-Wert der itemView des Inhabers auf 1.
Und ja, ich habe die Lösung für mein Problem gefunden, nachdem ich einen ganzen Tag leider verschwendet habe!
Hier ist mein Code für onBindViewHolder (...) Methoden:
onBindViewHolder (...) mit 2 Parametern:
onBindViewHolder (...) mit 3 Parametern:
Hier ist der Code der Methode, die ich in onClickListener von viewHolder's itemView in onCreateViewHolder (...) aufgerufen habe:
Hinweis: Sie können diese Position erhalten, indem Sie die Methode getAdapterPosition () Ihres viewHolder von onCreateViewHolder (...) aufrufen.
Ich habe auch die Methode getItemId (int position) wie folgt überschrieben:
und
setHasStableIds(true);
mein Adapterobjekt in Aktivität aufgerufen .Hoffe das hilft wenn keine der oben genannten Antworten funktioniert!
quelle
In meinem Fall gab es ein viel einfacheres Problem, aber es kann dem obigen Problem sehr ähnlich sein / sich so anfühlen. Ich hatte eine ExpandableListView mit Groupie in eine RecylerView konvertiert (mithilfe der ExpandableGroup-Funktion von Groupie). Mein ursprüngliches Layout hatte einen Abschnitt wie diesen:
Wenn layout_height auf "wrap_content" gesetzt war, fühlte sich die Animation von der erweiterten Gruppe zur reduzierten Gruppe so an, als würde sie blinken, aber es wurde wirklich nur von der "falschen" Position aus animiert (selbst nachdem die meisten Empfehlungen in diesem Thread ausprobiert wurden).
Das einfache Ändern von layout_height in match_parent auf diese Weise hat das Problem behoben.
quelle
Ich hatte ein ähnliches Problem und dies funktionierte bei mir. Sie können diese Methode aufrufen, um die Größe für den Bildcache festzulegen
quelle
Für meine Anwendung wurden einige Daten geändert, aber ich wollte nicht, dass die gesamte Ansicht blinkt.
Ich habe es gelöst, indem ich nur die alte Ansicht um 0,5 Alpha verkleinert und die neue Ansicht Alpha um 0,5 gestartet habe. Dies erzeugte einen weicheren Überblendungsübergang, ohne dass die Ansicht vollständig verschwand.
Leider konnte ich den DefaultItemAnimator aufgrund privater Implementierungen nicht in Unterklassen unterteilen, um diese Änderung vorzunehmen. Daher musste ich den Code klonen und die folgenden Änderungen vornehmen
in animateChange:
in animateChangeImpl:
quelle
Durch die Verwendung geeigneter Recyclerview-Methoden zum Aktualisieren von Ansichten wird dieses Problem behoben
Nehmen Sie zunächst Änderungen in der Liste vor
Dann benachrichtigen Sie mit
Hoffe das wird helfen !!
quelle
Versuchen Sie, die StableId in der Recycler-Ansicht zu verwenden. Der folgende Artikel erklärt es kurz
https://medium.com/@hanru.yeh/recyclerviews-views-are-blinking-when-notifydatasetchanged-c7b76d5149a2
quelle