J'utilise une implémentation simple de RecyclerView
tirée du site Web Android en utilisant un StaggeredGridLayoutManager
et je continue à recevoir cette erreur qui plante mon application:
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)
Par simple, je veux dire littéralement que c'est la même implémentation tirée de cette page sur leur site Web , la seule différence est que la disposition de mon élément de grille est un ImageView
et quelques TextView
s, donc je ne prendrai pas la peine de republier mon code.
Quelqu'un d'autre reçoit cette erreur et sait comment y remédier?
android
android-recyclerview
StackOverflowMaster
la source
la source
Réponses:
Cette erreur se produit si dans votre XML vous avez
android:animateLayoutChanges
défini sur true et que vous appeleznotifyDataSetChanged()
l'adaptateur de RecyclerView dans le code Java.Alors, évitez simplement d'utiliser
android:animateLayoutChanges
avec RecyclerViews.la source
RecyclerView
utiliseDefaultItemAnimator
par défaut.J'ai dû faire face à ce crash aussi et dans mon cas, cela n'avait rien à voir avec
android:animateLayoutChanges
.Le que
RecyclerView
nous construisions avait plus d'un type de vues et certains avaient des vuesEditText
en eux. Après un certain temps, nous avons épinglé le problème comme étant lié à la concentration. Ce bug se produit lors du recyclage desEditText
s et l'un d'eux est ciblé.Naturellement, nous avons essayé de dégager le focus lorsque de nouvelles données sont liées à une vue recyclée, mais cela n'a pas fonctionné avant d'
android:focusableInTouchMode="true"
être activéRecycleView
. En fait, c'est le seul changement qui était nécessaire à la fin pour que ce problème disparaisse.la source
android:focusableInTouchMode="true"
parce que cela n'arrive que parfois dans certains appareils (rarement) et je suppose que cela ne concerne pas mon problème, mais stack-trace pour un crash est presque le même.android:focusableInTouchMode="true"
m'a pas aidé du tout. J'ai donc effacé le focus dans leonViewDetachedFromWindow
rappel.public void onViewDetachedFromWindow(@NonNull RecyclerView.ViewHolder holder) { if (holder instanceof ItemViewHolder) { ItemViewHolder item = (ItemViewHolder) holder; if (item.editText.isFocused()) item.editText.clearFocus(); } }
J'ai supprimé la
android:animateLayoutChanges
propriété de mise en page et le problème a été résolu.la source
android:animateLayoutChanges
sur mon VR.Parmi les raisons pour lesquelles n'importe qui peut faire face à ce problème, vérifiez si vous avez défini l'attribut
android:animateLayoutChanges="true"
sur RecyclerView. Cela entraînera l'échec du recyclage et de la remise en place des éléments du RecyclerView. Supprimez-le et affectez l'attribut au conteneur parent du RecyclerView, tel qu'un LinearLayout / RelativeLayout et vous devriez voir le problème disparaître.la source
Cela m'a pris deux jours mais je n'ai pas pu contourner cela, à la fin, j'ai dû désactiver la prélecture de l'élément.
Lors de la configuration du gestionnaire de mise en page, vous pouvez simplement appeler
mGridLayoutManager.setItemPrefetchEnabled(false);
Cela a fait disparaître l'erreur pour moi. J'espère que cela sera utile pour quelqu'un.
la source
Lors de l'utilisation d'en-têtes collants slimfit, j'ai rencontré cette erreur. Cela a été causé par une mauvaise première position. J'ai la réponse ici
assurez-vous simplement que vous passez la valeur correcte pour mSectionFirstPosition
la source
item
t-il ici?J'ai rencontré ce problème ce matin, mais je ne suis pas confronté à la même raison que celle mentionnée ci-dessus.
Via le débogage, j'ai trouvé que la vue des éléments dans mon ViewHolder
mParent
et qu'elle n'est pas nulle, ce qui, dans le cas normal, ne devrait pas être nulle (c'est ce que dit le journal, "la vue attachée ne peut pas être recyclée", je pense que cela signifie que si la vue enfant est déjà attaché à un parent, cela causerait un échec lors du recyclage.)Mais je n'ai pas attaché la vue enfant à chaque fois manuellement. Et j'ai trouvé que c'était fait lorsque j'essayais de gonfler la vue enfant dans mon ViewHolder, quelque chose comme:
Et le dernier paramètre
attachToRoot
doit être faux.Après l'avoir changé en
false
, j'ai résolu mon problème.À propos, je ne vois que ce plantage s'est produit lorsque je mets à niveau ma bibliothèque de support vers la dernière version 25.0.0. Avant, j'utilisais la version 23.4.0 et je ne vois pas ce problème se produire. Je suppose qu'il devrait y avoir quelque chose de changé dans la dernière bibliothèque de support.
J'espère que cette aide.
la source
J'ai également rencontré la même erreur lors du défilement sur le
RecyclerView
: puis j'ai supprimé leanimateLayoutChanges="true"
fichier de mise en page pour queRecyclerView
tout fonctionne.la source
Dans mon cas, cela s'est produit parce que j'avais une
Transition
course en essayant de redimensionner le RecyclerView parce que le clavier logiciel était sur le point de s'afficher.Je l'ai corrigé en excluant RecyclerView de la
Transition
en utilisantTransition.excludeTarget(R.id.recyclerview, true);
la source
Il y a un certain nombre de raisons pour lesquelles cette exception est appelée. Dans mon cas, cela était dû à des animations en cours d'exécution, c'est pourquoi les vues sont toujours attachées et n'ont pas pu être supprimées de la vue. Ce n'est que lorsque l'animation est terminée que la vue peut être supprimée et recyclée.
Il existe deux types d'animation qui pourraient affecter le recyclage de la vue de recyclage.
1) Est-ce que le
RecyclerView.ItemAnimator
-ce que - cela ne devrait pas être le problème. Cela devrait être à peu près sûr à utiliser car il vérifie les vues attachées et mises au rebut et gère correctement le recyclage.2)
android:animateLayoutChanges="true"
ouTransitionManager.beginDelayedTransition()
ou TransitionManager.go (), etc. - Ces animations s'exécutent toutes seules et saisissent les éléments à animer. Il en résulte que les vues doivent être attachées jusqu'à ce que l'animation soit terminée. Les recyclerview n'ont aucune connaissance de ces animations car elles sont hors de son champ d'application. Par conséquent, ilsrecyclerview
pourraient essayer de recycler un élément en pensant qu'il pourrait être recyclé correctement, mais le problème est que ces API conservent les vues jusqu'à ce que l'animation soit terminée.Si vous utilisez
android:animateLayoutChanges="true"
ouTransitionManager.beginDelayedTransition()
ou TransitionManager.go (), etc., supprimez simplement leRecyclerView
et ses enfants de l'animation.Vous pouvez simplement le faire en saisissant le
Transition
et en appelantRemarque:
Notez qu'il est important d'utiliser
Transition.excludeChildren()
pour exclure tous lesRecyclerview
enfants de l'animation et pas seulementRecyclerview
lui - même.la source
Transition.excludeChildren
. Vous instanciez un objet de transition comme:,val transition = AutoTransition()
appelezexcludeChildren(recyclerView, true)
cet objet et passez-le àbeginDelayedTransaction() as the second parameter
.J'obtenais moi aussi cette erreur chaque fois que j'avais animateLayoutChanges = "true" dans le fichier de mise en page pour RecyclerView. Supprimez cet attribut et l'erreur disparaîtra!
la source
Alors que dans mon cas, c'était la suppression
animateOnLayoutChange
de recyclerView qui corrigeait le plantage, j'avais toujours besoin de la possibilité d'animer les modifications de mise en page dans le viewHolder. Pour que cela fonctionne, l'LinearLayout' in the view holder needs the
animateOnLayoutChange 'sur true, mais j'avais besoinnotifyItemChanged
de l'adaptateur. Cela a ensuite permis aux deux animations layoutTransition de démarrer (pour développer et réduire le viewHolder), et évite également l'exception abandonnée. Alors oui, évitez de mettre l'animateOnLayoutChange sur le recylcerView et utilisez les différentes méthodes de notification pour activer les animations par défaut lors des changements de taille de vue.la source
Je résous ce problème en supprimant
parent.addView()
dansonCreateViewHolder
C'est mon code
Fonction à
android.support.v7.widget.RecyclerViewRecycler.recyclerViewHolderinternal()
vérifier si mon bouton a déjà un parent ou non. Qui si nous ajoutons un bouton au parent, il sera également assignéRecyclerView
à samParent
variable.la source
J'ai vu cela se produire pour moi lorsque j'ai utilisé un objet personnalisé dans
ViewHolder
leRecyclerView
adaptateur.Pour résoudre le problème, j'ai effacé l'objet personnalisé qui, dans mon cas, était une minuterie dans
onViewRecycled(ViewHolder holder)
l'adaptateur comme ci-dessous:Cela a corrigé le bogue.
la source
la source
1 、
remove
: supprimer les données de la liste.2 、
notifyDataSetChanged
: notifyDataSetChanged ();3 、
notifyItemRemoved
: montrer l'animation.4 、
notifyItemRangeChanged
: la taille de la vue et redessinez laviewHolders(onBindViewHolder methods)
la source
notifyItemRemoved
lors de la suppressionfooter
et des plantages d'application, changez-le ennotifyDataSetChanged
et maintenant cela fonctionne bien. merciDans mon cas, j'ai utilisé le
TransitionManager.beginDelayedTransition()
avant d'ajouter une vue au-dessus de recyclerView. J'ai supprimé leTransitionManager.beginDelayedTransition()
et pas de crash.la source
J'ai résolu ce problème en appelant
dans le constructeur de l'adaptateur et le remplacement
getItemId
dans l'adaptateur:la source
Supprimer
android:animateLayoutChanges="true"
de la recycleview ou définirandroid:animateLayoutChanges="false"
la source
j'utilise
com.squareup.picasso.RequestCreator
pour redimensionner dynamiquement la taille d'ImageView après le téléchargement de l'image à partir d'Internet, et enregistre la largeur et la hauteur redimensionnées pour préserver la taille de la vue. J'ai obtenu cette exception parce que j'ai enregistré
LayoutParams
dans unMap
, et dans mon onBindViewHolder, je l'ai récupéré et l'ai directement défini sur monImageView
. Je corrige cela en utilisantImmutablePair<Integer, Integer>
uniquement la taille d'ImageView plutôt que de nombreux autres états, et j'utilise le code suivant pour le restaurer.la source
Pour moi, le même bug causé par un LayoutTransition sur un ViewGroup de niveau supérieur.
la source
Permettez-moi d'ajouter une autre solution possible pour ce type de problème, s'il vous plaît. J'ai eu le même problème avec la bibliothèque superSlim pour les en-têtes collants
RecyclerView
. J'avais l'habitudeMatrixCursor
de définir les données surRecyclerViewCursorAdapter
. La raison de ce problème était que les colonnes d'ID sont égales à0
pour tous les en-têtes. J'espère que cela aiderait quelqu'un à économiser quelques jours de débogage.la source
Dans mon cas, le problème était dû à la mise en œuvre incorrecte de cette méthode
public long getItemId(int position)
(remplacé parRecyclerView.Adapter
méthode).L'ancien code obtiendra deux identifiants différents pour le même élément (dans mon cas, il s'agit de l'élément de pied de page), après avoir corrigé l'implémentation, le problème a disparu.
la source
Solution de contournement si la raison de l'exception est ce que itemView a un parent. Dans le code, où vous avez notifyItemRemoved (position), supprimez itemView de RecyclerView:
la source
Un cas particulier qui s'est produit pour moi était que j'avais un membre de vue dans l'adaptateur et que j'étais paresseux instanciant une vue qu'il n'est pas nécessaire de faire avec la vue de recyclage.
Cela va également à l'encontre des principes de recyclage des vues qui, dans ce cas, vous permettent de stocker une référence à la vue. Je donne un exemple rapide ci-dessous:
la source
cette exception n'est pas cause de
ou
cette réponse correcte finale est simplement parce que vous avez défini un mauvais LayoutParams .
le nomLP est OK. le nomLP2 se produit le crash .bug est ici.
J'essaye toutes les réponses de cette page. croyez-moi.
la source
J'ai eu ce problème parce que j'Ecraser
equals()
ethashcode()
méthodeViewHolder
deRecyclerView
.ViewHolder en calculant l' égalité des données et hashcode, alors la logique de recyclage ne marchait pas et écrasé, je retire tout l'écrasement et fixe.la source