RecyclerView se bloquea cuando "las vistas desechadas o conectadas no se pueden reciclar"

Estoy usando una implementación sencilla de RecyclerView tomada del sitio web de Android usando un StaggeredGridLayoutManager y sigo recibiendo este error que bloquea mi aplicación:

 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) 

Por simple, literalmente significa que es la misma implementación tomada de esta página en su sitio web , la única diferencia es que el diseño de mi elemento de la cuadrícula es un ImageView y un par de TextView s, así que no me molestará reposting mi código.

¿Alguien más que este error y sabe cómo tratar con él?

Este error se produce si en tu XML tienes android:animateLayoutChanges establecido en true y llamas notifyDataSetChanged() en el adaptador de RecyclerView en el código Java.

Así que evita usar android:animateLayoutChanges con RecyclerViews.

He tenido que lidiar con este accidente también y en mi caso no tenía nada que ver con android:animateLayoutChanges .

El RecyclerView que estábamos construyendo tenía más de un tipo de vistas en él y algunos tenían EditText s en ellos. Después de un tiempo fijamos la cuestión de estar relacionado con el foco. Este error ocurre mientras se recicla EditText s y uno de ellos está enfocado.

Naturalmente tratamos de borrar el foco cuando los nuevos datos están siendo enlazados a una vista reciclada, pero eso no funcionó hasta android:focusableInTouchMode="true" se establece en RecycleView . En realidad, ese es el único cambio que se necesitaba al final para que este asunto desapareciera.

Quité el "android: animateLayoutChanges" de la propiedad de diseño y el problema se ha resuelto.

Durante el uso de encabezados pegajosos slimfit encontré este error. Fue causado debido a la configuración de la primera posición incorrecta. Tengo la respuesta aquí

 public void onBindViewHolder(MainViewHolder holder, int position) { final View itemView = holder.itemView; final LayoutManager.LayoutParams params = LayoutManager.LayoutParams.from(itemView.getLayoutParams()); params.setSlm(LinearSLM.ID); params.width = ViewGroup.LayoutParams.MATCH_PARENT; params.setFirstPosition(item.mSectionFirstPosition); itemView.setLayoutParams(params); } 

Sólo asegúrese de que está pasando el valor correcto para mSectionFirstPosition

He resuelto esta cuestión esta mañana, pero no me enfrento a la misma razón mencionada anteriormente.

A través de depuración encontré que la vista de elemento en mi ViewHolder tiene mParent y no es nulo, que en caso normal debería ser ninguno (que es lo que dice el registro, "vista adjunta no se puede reciclar", creo que significa que si el niño Vista ya está unido a un padre, que algunos como causar el fracaso al reciclar.)

Pero no adjuntar la vista de niño cada vez manualmente. Y descubrí que se hace cuando intento inflar la vista secundaria en mi ViewHolder, algo así como:

 layoutInflater.inflate(@LayoutRes int resource, @Nullable ViewGroup root, boolean attachToRoot) 

Y el último parámetro attachToRoot debe ser falso.

Después de cambiarlo a false , arreglé mi problema.

Por cierto, sólo veo que este accidente ocurrió cuando actualizé mi biblioteca de soporte a la última versión 25.0.0. Antes de usar la versión 23.4.0 y no veo este problema sucediendo. Supongo que debería haber algo cambiado en la última biblioteca de soporte.

Espero que esto ayude.

parent.addView() este problema quitando parent.addView() en onCreateViewHolder

Este es mi codigo

 public MyViewHolder onCreateViewwHolder(ViewGroup parent, int viewType) { Button addButton = new Button(context); //parent.addView(addButton); return new MyViewHolder(addButton); } 

Función en android.support.v7.widget.RecyclerViewRecycler.recyclerViewHolderinternal() comprobar si mi botón ya tiene un padre o no. Que si agregamos el botón a padre, también será asignar RecyclerView a su variable mParent .

Entre las razones por las que cualquiera puede hacer frente a este problema, comprueba si has establecido el atributo android:animateLayoutChanges="true" en el RecyclerView. Esto hará que el reciclaje y la reinstalación de los elementos de RecyclerView fallen. Quítelo y asigne el atributo al contenedor principal de RecyclerView, como un LinearLayout / RelativeLayout y debería ver el problema desaparecer.

Vi esto suceder para mí cuando utilicé un objeto de encargo en el ViewHolder para el adaptador de RecyclerView .

Para corregir el problema he borrado el objeto personalizado que en mi caso era un temporizador en el onViewRecycled(ViewHolder holder) para el adaptador como se muestra a continuación:

  public void onViewRecycled(ViewHolder holder) { if(holder instanceof EntityViewHolder) { if(((EntityViewHolder)holder).timer != null) { ((EntityViewHolder) holder).timer.cancel(); } } super.onViewRecycled(holder); } 

Esto arregló el error.

  /** * Informs the recycler whether this item can be recycled. Views which are not * recyclable will not be reused for other items until setIsRecyclable() is * later set to true. Calls to setIsRecyclable() should always be paired (one * call to setIsRecyclabe(false) should always be matched with a later call to * setIsRecyclable(true)). Pairs of calls may be nested, as the state is internally * reference-counted. * * @param recyclable Whether this item is available to be recycled. Default value * is true. * * @see #isRecyclable() */ public final void setIsRecyclable(boolean recyclable) { mIsRecyclableCount = recyclable ? mIsRecyclableCount - 1 : mIsRecyclableCount + 1; if (mIsRecyclableCount < 0) { mIsRecyclableCount = 0; if (DEBUG) { throw new RuntimeException("isRecyclable decremented below 0: " + "unmatched pair of setIsRecyable() calls for " + this); } Log.e(VIEW_LOG_TAG, "isRecyclable decremented below 0: " + "unmatched pair of setIsRecyable() calls for " + this); } else if (!recyclable && mIsRecyclableCount == 1) { mFlags |= FLAG_NOT_RECYCLABLE; } else if (recyclable && mIsRecyclableCount == 0) { mFl`enter code here`ags &= ~FLAG_NOT_RECYCLABLE; } if (DEBUG) { Log.d(TAG, "setIsRecyclable val:" + recyclable + ":" + this); } } 

1, remove : quitar datos de la lista.

2, notifyDataSetChanged : notifyDataSetChanged ();

3, notifyItemRemoved : mostrar animación.

4, notifyItemRangeChanged : el tamaño de la vista de rango y volver a dibujar los viewHolders(onBindViewHolder methods)

Solucioné este problema llamando al

 setHasStableIds(true); 

En el constructor del adaptador y sobreescribir getItemId en el adaptador:

 @Override public long getItemId(int position) { return position; } 

Utilizo com.squareup.picasso.RequestCreator

 public void into(android.widget.ImageView target, Callback callback) 

Para cambiar el tamaño de ImageView de forma dinámica después de descargar la imagen de Internet y guarda el ancho y la altura redimensionados para conservar el tamaño de la vista. Conseguí esta excepción porque ahorré LayoutParams en un Map , y en mi onBindViewHolder, lo recuperé y fijé directamente a mi ImageView . Puedo solucionar esto con ImmutablePair<Integer, Integer> para almacenar el tamaño de ImageView en lugar de muchos otros estados, y usar el siguiente código para restaurarlo.

 ViewGroup.LayoutParams params = image.getLayoutParams(); params.width = widthAndHeight.getLeft(); params.height = widthAndHeight.getRight(); image.setLayoutParams(params); 

Para mí el mismo error con causado por LayoutTransition en un nivel superior ViewGroup.

Permítanme añadir otra solución posible para este tipo de problema, por favor. Tuve el mismo problema con la biblioteca superSlim para encabezados pegajosos en RecyclerView . Utilicé MatrixCursor para establecer datos en RecyclerViewCursorAdapter . El motivo de este problema fue columnas de ID iguales a 0 para todos los encabezados. Espero que ayude a alguien a ahorrar dos días de depuración.

En mi caso el problema fue debido a la implementación incorrecta de este método public long getItemId(int position) (reemplazado por el método RecyclerView.Adapter ).

El código antiguo obtendrá dos identificaciones diferentes para el mismo elemento (en mi caso es el elemento de pie de página), después de corregir la implementación del problema.

En mi caso, utilicé TransitionManager.beginDelayedTransition() antes de añadir una vista encima del recyclerView. Quité el TransitionManager.beginDelayedTransition() y no accidente.

Un caso peculiar que ocurrió para mí era que tenía un miembro de la visión en el adaptador y era perezoso instantiating una visión que no hay ninguna necesidad de hacer con la visión del reciclar.

También va en contra de los principios de reciclar vistas que como su almacenamiento de una referencia a la vista en este caso. Doy un ejemplo rápido a continuación:

 // typically we would do this in a grid view adapter: View v; // ... if(v = null){ v = LayoutInflater.inflate ...; } // Now with recycle view there is NO need to store a reference to View and lazy instantiate. So get rid of your View v member 
  • Mostrar la vista personalizada bajo el elemento RecyclerView deslizado
  • RecyclerView vuelve a calcular WRAP_CONTENT
  • Distancia entre RecyclerView demasiado lejos
  • No hay animación en la eliminación de artículos en RecyclerView
  • Cómo agregar Horizontal Recyclerview como un encabezado para Vertical Recyclerview?
  • Java.lang.NullPointerException en android.support.v7.widget.RecyclerView.onMeasure
  • NotifyDataSetChanged no actualiza RecyclerView
  • Twowayview agrega automáticamente relleno al desplazarse
  • Android - Cómo detener la recarga de imágenes en Recyclerview al desplazarse
  • RecyclerView - saltar a la posición, luego desplazamiento suave hasta la parte superior
  • ¿Cómo se relaciona la posición de un adaptador de RecyclerView con el índice de su conjunto de datos?
  • Interesting Posts
    FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.