Ich verwende eine einfache Implementierung RecyclerView
von der Android-Website mit a StaggeredGridLayoutManager
und erhalte immer wieder den Fehler, der meine App zum Absturz bringt:
java.lang.IllegalArgumentException: Scrapped or attached views may not be recycled. isScrap:false isAttached:true
at android.support.v7.widget.RecyclerView$Recycler.recycleViewHolderInternal(RecyclerView.java:3501)
at android.support.v7.widget.RecyclerView$LayoutManager.scrapOrRecycleView(RecyclerView.java:5355)
at android.support.v7.widget.RecyclerView$LayoutManager.detachAndScrapAttachedViews(RecyclerView.java:5340)
at android.support.v7.widget.StaggeredGridLayoutManager.onLayoutChildren(StaggeredGridLayoutManager.java:572)
at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:1918)
at android.support.v7.widget.RecyclerView.onLayout(RecyclerView.java:2155)
at android.view.View.layout(View.java:14008)
at android.view.ViewGroup.layout(ViewGroup.java:4373)
at android.widget.RelativeLayout.onLayout(RelativeLayout.java:1021)
at android.view.View.layout(View.java:14008)
at android.view.ViewGroup.layout(ViewGroup.java:4373)
at android.widget.FrameLayout.onLayout(FrameLayout.java:448)
at android.view.View.layout(View.java:14008)
at android.view.ViewGroup.layout(ViewGroup.java:4373)
at android.widget.FrameLayout.onLayout(FrameLayout.java:448)
at android.view.View.layout(View.java:14008)
at android.view.ViewGroup.layout(ViewGroup.java:4373)
at android.support.v7.internal.widget.ActionBarOverlayLayout.onLayout(ActionBarOverlayLayout.java:502)
at android.view.View.layout(View.java:14008)
at android.view.ViewGroup.layout(ViewGroup.java:4373)
at android.widget.FrameLayout.onLayout(FrameLayout.java:448)
at android.view.View.layout(View.java:14008)
at android.view.ViewGroup.layout(ViewGroup.java:4373)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1663)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1521)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1434)
at android.view.View.layout(View.java:14008)
at android.view.ViewGroup.layout(ViewGroup.java:4373)
at android.widget.FrameLayout.onLayout(FrameLayout.java:448)
at android.view.View.layout(View.java:14008)
at android.view.ViewGroup.layout(ViewGroup.java:4373)
at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:1892)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1711)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:989)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:4351)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:749)
at android.view.Choreographer.doCallbacks(Choreographer.java:562)
at android.view.Choreographer.doFrame(Choreographer.java:532)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:735)
at android.os.Handler.handleCallback(Handler.java:725)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5041)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
at dalvik.system.NativeStart.main(Native Method)
Mit einfach meine ich wörtlich, dass es sich um dieselbe Implementierung handelt, die von dieser Seite auf ihrer Website übernommen wurde. Der einzige Unterschied besteht darin, dass das Layout meines Rasterelements ein ImageView
und ein paar TextView
Sekunden beträgt, sodass ich meinen Code nicht erneut veröffentlichen muss.
Bekommt sonst noch jemand diesen Fehler und weiß, wie man damit umgeht?
android
android-recyclerview
StackOverflowMaster
quelle
quelle
Antworten:
Dieser Fehler wird verursacht, wenn Sie in Ihrem XML den Wert
android:animateLayoutChanges
true festgelegt haben undnotifyDataSetChanged()
den RecyclerView-Adapter im Java-Code aufrufen .Vermeiden Sie daher die Verwendung
android:animateLayoutChanges
mit RecyclerViews.quelle
RecyclerView
verwendetDefaultItemAnimator
standardmäßig.Ich musste mich auch mit diesem Absturz auseinandersetzen und in meinem Fall hatte es nichts damit zu tun
android:animateLayoutChanges
.Das, das
RecyclerView
wir bauten, hatte mehr als eine Art von Ansichten und einige hattenEditText
s in ihnen. Nach einer Weile haben wir das Problem auf fokusbezogen festgelegt. Dieser Fehler tritt beim Recycling aufEditText
und einer von ihnen ist fokussiert.Natürlich haben wir versucht, den Fokus zu löschen, wenn neue Daten an eine recycelte Ansicht gebunden werden, aber das hat erst funktioniert, wenn sie
android:focusableInTouchMode="true"
aktiviert sindRecycleView
. Tatsächlich ist dies die einzige Änderung, die am Ende erforderlich war, damit dieses Problem behoben werden konnte.quelle
android:focusableInTouchMode="true"
weil es nur manchmal in einigen Geräten passiert (selten) und ich vermute, dass es nicht mit meinem Problem zusammenhängt, aber Stack-Trace für Absturz ist fast gleich.android:focusableInTouchMode="true"
hat mir überhaupt nicht geholfen. Also habe ich den Fokus imonViewDetachedFromWindow
Rückruf gelöscht .public void onViewDetachedFromWindow(@NonNull RecyclerView.ViewHolder holder) { if (holder instanceof ItemViewHolder) { ItemViewHolder item = (ItemViewHolder) holder; if (item.editText.isFocused()) item.editText.clearFocus(); } }
Ich habe die
android:animateLayoutChanges
Eigenschaft aus dem Layout entfernt und das Problem wurde behoben.quelle
android:animateLayoutChanges
auf mein Wohnmobil legte.Überprüfen Sie unter anderem, ob dieses Problem
android:animateLayoutChanges="true"
auf RecyclerView festgelegt wurde. Dies führt dazu, dass das Recycling und das erneute Anbringen der RecyclerView-Elemente fehlschlägt. Entfernen Sie es und weisen Sie das Attribut dem übergeordneten Container von RecyclerView zu, z. B. einem LinearLayout / RelativeLayout. Das Problem sollte dann behoben sein.quelle
Ich habe zwei Tage gebraucht, konnte das aber nicht umgehen. Am Ende musste ich den Artikel-Prefetch deaktivieren.
Beim Einstellen des Layout-Managers können Sie einfach anrufen
mGridLayoutManager.setItemPrefetchEnabled(false);
Es hat den Fehler für mich verschwinden lassen. Hoffe, es wird für jemanden nützlich sein.
quelle
Bei der Verwendung von Slimfit Sticky Headern ist dieser Fehler aufgetreten. Es wurde verursacht, weil die erste Position falsch eingestellt wurde. Ich habe die Antwort hier
Stellen Sie einfach sicher, dass Sie den korrekten Wert für mSectionFirstPosition übergeben
quelle
item
hierIch bin heute Morgen auf dieses Problem gestoßen, habe aber nicht den gleichen Grund wie oben erwähnt.
Beim Debuggen habe ich festgestellt, dass die Elementansicht in meinem ViewHolder
mParent
nicht null ist, was im Normalfall keine sein sollte (das ist das Protokoll mit der Aufschrift "Angehängte Ansicht darf nicht recycelt werden"). Ich denke, dies bedeutet, dass die untergeordnete Ansicht ist bereits an ein Elternteil angehängt, würde dies beim Recycling zu Fehlern führen.)Aber ich habe die untergeordnete Ansicht nicht jedes Mal manuell angehängt. Und ich habe festgestellt, dass dies erledigt ist, wenn ich versuche, die untergeordnete Ansicht in meinem ViewHolder aufzublähen.
Und der letzte Parameter
attachToRoot
sollte falsch sein.Nachdem ich es geändert habe
false
, habe ich mein Problem behoben.Ich sehe diesen Absturz übrigens nur, wenn ich meine Support-Bibliothek auf die neueste Version 25.0.0 aktualisiere. Bevor ich Version 23.4.0 verwendet habe und dieses Problem nicht auftritt. Ich denke, in der neuesten Support-Bibliothek sollte sich etwas geändert haben.
Ich hoffe das hilft.
quelle
Ich habe auch den gleichen Fehler beim Scrollen auf dem
RecyclerView
: dann habe ichanimateLayoutChanges="true"
in der Layout-Datei entfernt,RecyclerView
dann hat alles funktioniert.quelle
In meinem Fall geschah dies, weil ich
Transition
beim Versuch, die Größe von RecyclerView zu ändern, ausgeführt wurde, weil die Softwaretastatur angezeigt werden sollte.Ich reparierte es meinen Ausschluß den RecyclerView von dem
Transition
durch die VerwendungTransition.excludeTarget(R.id.recyclerview, true);
quelle
Auch ich bekam diesen Fehler, wenn ich animateLayoutChanges = "true" in der Layoutdatei für RecyclerView hatte. Löschen Sie dieses Attribut und der Fehler verschwindet!
quelle
Es gibt eine Reihe von Gründen, warum diese Ausnahme aufgerufen wird. In meinem Fall lag es an laufenden Animationen, weshalb die Ansichten immer noch angehängt sind und nicht in die Ansicht entfernt werden konnten. Erst wenn die Animation beendet ist, kann die Ansicht entfernt und recycelt werden.
Es gibt zwei Arten von Animationen, die sich auf das Recycling der Recyclingansicht auswirken können.
1) Ist das
RecyclerView.ItemAnimator
- das sollte nicht das Problem sein. Dies sollte ziemlich sicher zu verwenden sein, da es nach Anhängen und Verschrottungen sucht und das Recycling ordnungsgemäß handhabt.2)
android:animateLayoutChanges="true"
oderTransitionManager.beginDelayedTransition()
oder TransitionManager.go () usw. - Diese Animationen werden von selbst ausgeführt und greifen auf die zu animierenden Elemente zu. Dies führt dazu, dass die Ansichten zwangsweise angehängt werden müssen, bis die Animation beendet ist. Das Recyclerview hat keine Kenntnis von diesen Animationen, da es außerhalb seines Bereichs liegt. Daher wirdrecyclerview
möglicherweise versucht, ein Element zu recyceln, da es möglicherweise ordnungsgemäß recycelt werden kann. Das Problem besteht jedoch darin, dass diese APIs die Ansichten bis zum Abschluss der Animation beibehalten.Wenn Sie
android:animateLayoutChanges="true"
oderTransitionManager.beginDelayedTransition()
oder TransitionManager.go () usw. verwenden, entfernen Sie einfach dasRecyclerView
und seine untergeordneten Elemente aus der Animation.Sie können dies einfach tun, indem Sie das ergreifen
Transition
und anrufenHinweis:
Beachten Sie, dass es wichtig ist
Transition.excludeChildren()
, alleRecyclerview
Kinder von der Animation auszuschließen und nicht nur sichRecyclerview
selbst.quelle
Transition.excludeChildren
. Sie instanziieren ein Übergangsobjekt wie :val transition = AutoTransition()
, rufenexcludeChildren(recyclerView, true)
dieses Objekt auf und übergeben es anbeginDelayedTransaction() as the second parameter
.Während in meinem Fall das Entfernen
animateOnLayoutChange
aus der recyclerView den Absturz behebte, brauchte ich dennoch die Möglichkeit, die Layoutänderungen im viewHolder zu animieren. Damit dies funktioniert, mussLinearLayout' in the view holder needs the
animateOnLayoutChange 'auf true gesetzt werden, aber ich musstenotifyItemChanged
auf den Adapter. Dadurch konnten beide layoutTransition-Animationen gestartet werden (zum Erweitern und Reduzieren des viewHolder) und die verschrottete Ausnahme vermieden werden. Vermeiden Sie es also, animateOnLayoutChange in die recylcerView einzufügen, und verwenden Sie die verschiedenen Benachrichtigungsmethoden, um die Standardanimationen für Änderungen der Ansichtsgröße zu aktivieren.quelle
Ich dieses Problem lösen , indem
parent.addView()
inonCreateViewHolder
Das ist mein Code
Funktion bei der
android.support.v7.widget.RecyclerViewRecycler.recyclerViewHolderinternal()
Überprüfung, ob meine Schaltfläche bereits ein übergeordnetes Element hat oder nicht. Wenn wir dem übergeordneten Element eine Schaltfläche hinzufügen, wird diese auchRecyclerView
seinermParent
Variablen zugewiesen .quelle
Ich habe gesehen, dass dies für mich passiert ist, als ich ein benutzerdefiniertes Objekt im
ViewHolder
für denRecyclerView
Adapter verwendet habe.Um das Problem zu beheben, habe ich das benutzerdefinierte Objekt, das in meinem Fall ein Timer
onViewRecycled(ViewHolder holder)
für den Adapter war, wie folgt gelöscht :Dies hat den Fehler behoben.
quelle
quelle
1 :
remove
: Daten aus der Liste entfernen.2 、
notifyDataSetChanged
: notifyDataSetChanged ();3
notifyItemRemoved
animation : Animation anzeigen.4 、
notifyItemRangeChanged
: Größe der Bereichsansicht und Neuzeichnen derviewHolders(onBindViewHolder methods)
quelle
notifyItemRemoved
wenn das Entfernenfooter
und App abstürzt, ändern Sie es innotifyDataSetChanged
und jetzt funktioniert es in Ordnung. dankeIn meinem Fall habe ich das verwendet,
TransitionManager.beginDelayedTransition()
bevor ich eine Ansicht über der recyclerView hinzugefügt habe. Ich habe das entferntTransitionManager.beginDelayedTransition()
und keinen Absturz.quelle
Ich habe dieses Problem durch einen Anruf gelöst
im Konstruktor des Adapters und Überschreiben
getItemId
im Adapter:quelle
android:animateLayoutChanges="true"
Aus der Recyclingansicht entfernen oder einstellenandroid:animateLayoutChanges="false"
quelle
ich benutze
com.squareup.picasso.RequestCreator
Zum dynamischen Ändern der Größe von ImageView nach dem Herunterladen von Bildern aus dem Internet und Speichern der Größe und Höhe der Größe, um die Ansichtsgröße beizubehalten. Ich habe diese Ausnahme erhalten, weil ich sie
LayoutParams
in a gespeichertMap
und in meinem onBindViewHolder abgerufen und direkt auf meine gesetzt habeImageView
. IchImmutablePair<Integer, Integer>
behebe dies, indem ich nur die Größe von ImageView und nicht viele andere Zustände speichere und den folgenden Code verwende, um sie wiederherzustellen.quelle
Für mich der gleiche Fehler, der durch eine LayoutTransition auf einer übergeordneten ViewGroup verursacht wurde.
quelle
Lassen Sie mich bitte eine weitere mögliche Lösung für diese Art von Problem hinzufügen. Ich hatte das gleiche Problem mit der superSlim- Bibliothek für klebrige Header in
RecyclerView
. ich benutzteMatrixCursor
Daten auf gesetztRecyclerViewCursorAdapter
. Der Grund für dieses Problem war, dass ID-Spalten0
für alle Header gleich sind. Hoffe, das würde jemandem helfen, ein paar Tage Debugging zu sparen.quelle
In meinem Fall lag das Problem an der fehlerhaften Implementierung dieser Methode
public long getItemId(int position)
(überschrieben vonRecyclerView.Adapter
Methode).Der alte Code erhält zwei verschiedene IDs für dasselbe Element (in meinem Fall ist es das Fußzeilenelement), nachdem das Problem behoben wurde.
quelle
Problemumgehungslösung, wenn der Grund für die Ausnahme das übergeordnete Element von itemView ist. Entfernen Sie im Code, in dem Sie notifyItemRemoved (Position) haben, itemView aus RecyclerView:
quelle
Ein besonderer Fall, der für mich auftrat, war, dass ich ein Ansichtsmitglied im Adapter hatte und faul war, eine Ansicht zu instanziieren, die mit der Recyclingansicht nicht zu tun hat.
Dies verstößt auch gegen die Prinzipien der Recycling-Ansichten, die in diesem Fall als Speicherung eines Verweises auf die Ansicht dienen. Ich gebe ein kurzes Beispiel unten:
quelle
Diese Ausnahme ist nicht Ursache von
oder
Diese endgültige richtige Antwort ist nur, weil Sie ein FALSCHES LayoutParams festgelegt haben .
Der Name LP ist OK. Der Name LP2 tritt auf, wenn der Absturz .bug hier ist.
Ich versuche alle Antworten dieser Seite. Vertrau mir.
quelle
Ich hatte dieses Problem , weil ich überschreiben
equals()
undhashcode()
VerfahrenViewHolder
vonRecyclerView
.ViewHolder durch Datengleichheit Berechnung und hashcode, dann ist die Recycling - Logik hat nicht funktioniert und abgestürzt, ich entfernen Sie einfach das Überschreiben und fixiert.quelle