Estoy tratando de actualizar los elementos de una vista de reciclaje usando notifyDataSetChanged ().
Este es mi método onBindViewHolder () en el adaptador de reciclaje.
@Override
public void onBindViewHolder(ViewHolder viewHolder, int position) {
//checkbox view listener
viewHolder.getCheckbox().setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
//update list items
notifyDataSetChanged();
}
});
}
Lo que quiero hacer es actualizar los elementos de la lista, después de marcar una casilla de verificación. Sin embargo, recibo una excepción ilegal:"Cannot call this method while RecyclerView is computing a layout or scrolling"
java.lang.IllegalStateException: Cannot call this method while RecyclerView is computing a layout or scrolling
at android.support.v7.widget.RecyclerView.assertNotInLayoutOrScroll(RecyclerView.java:1462)
at android.support.v7.widget.RecyclerView$RecyclerViewDataObserver.onChanged(RecyclerView.java:2982)
at android.support.v7.widget.RecyclerView$AdapterDataObservable.notifyChanged(RecyclerView.java:7493)
at android.support.v7.widget.RecyclerView$Adapter.notifyDataSetChanged(RecyclerView.java:4338)
at com.app.myapp.screens.RecycleAdapter.onRowSelect(RecycleAdapter.java:111)
También usé notifyItemChanged (), la misma excepción. ¿Alguna forma secreta de actualizar para notificar al adaptador que algo cambió?
android
android-recyclerview
Arturo
fuente
fuente
Respuestas:
Debe mover el método 'setOnCheckedChangeListener ()' a ViewHolder, que es la clase interna en su adaptador.
onBindViewHolder()
No es un método de inicializaciónViewHolder
. Este método es el paso de actualizar cada elemento de reciclaje. Cuando llamenotifyDataSetChanged()
,onBindViewHolder()
se le llamará como el número de cada artículo veces.Así que si usted
notifyDataSetChanged()
pone enonCheckChanged()
e inicializar casilla de verificaciónonBindViewHolder()
, obtendrá IllegalStateException debido a la llamada al método circular.haga clic en la casilla de verificación -> onCheckedChanged () -> notifyDataSetChanged () -> onBindViewHolder () -> establezca la casilla de verificación -> onChecked ...
Simplemente, puede solucionar esto colocando una bandera en Adaptador.
prueba esto,
fuente
AdapterViewObserver
mientras estáonBindViewHolder()
en progreso.Puede reiniciar el escucha anterior antes de realizar cambios y no obtendrá esta excepción.
fuente
El uso de un
Handler
para agregar elementos y llamarnotify...()
desde este meHandler
solucionó el problema.fuente
No lo sé bien, pero también tuve el mismo problema. Resolví esto usando
onClickListner
elcheckbox
¡Prueba esto, esto puede ayudar!
fuente
fuente
Cuando tienes el mensaje de error:
Simple, solo haz lo que causa la excepción en:
fuente
Encontró una solución simple:
Aquí creamos un ejecutable para notificar a ItemChanged para una posición cuando la vista de reciclaje está lista para manejarla.
fuente
su elemento CheckBox está cambiando dibujable cuando llama
notifyDataSetChanged();
para que se produzca esta excepción. Intente llamarnotifyDataSetChanged();
en la publicación de su vista. Por ejemplo:fuente
Al principio pensé que la respuesta de Moonsoo (la respuesta aceptada) no funcionaría para mí porque no puedo inicializar mi
setOnCheckedChangeListener()
en el constructor ViewHolder porque necesito vincularlo cada vez para que obtenga una variable de posición actualizada. Pero me llevó mucho tiempo darme cuenta de lo que estaba diciendo.Aquí hay un ejemplo de la "llamada al método circular" de la que está hablando:
El único problema con esto es que cuando necesitamos inicializar el interruptor para que se active o desactive (desde el estado guardado en el pasado, por ejemplo), está llamando al oyente, que podría llamar a
nofityItemRangeChanged
qué llamadasonBindViewHolder
nuevamente. No puede llamaronBindViewHolder
cuando ya está enonBindViewHolder
], porque no puede hacerlonotifyItemRangeChanged
si ya está en medio de la notificación de que el rango de elementos ha cambiado. Pero solo necesitaba actualizar la interfaz de usuario para mostrarla activada o desactivada, no queriendo realmente desencadenar nada.Aquí está la solución que aprendí de la respuesta de JoniDS que evitará el ciclo infinito. Siempre que configuremos el oyente como "nulo" antes de configurar Checked, actualizará la interfaz de usuario sin activar el oyente, evitando el bucle infinito. Entonces podemos configurar el oyente después.
Código de JoniDS:
Solución completa a mi ejemplo:
fuente
¿Por qué no verificar el
RecyclerView.isComputingLayout()
estado de la siguiente manera?fuente
Mientras el administrador de diseño vincula el elemento, es muy probable que esté configurando el estado marcado de su casilla de verificación, que está activando la devolución de llamada.
Por supuesto, esto es una conjetura porque no publicó el seguimiento completo de la pila.
No puede cambiar el contenido del adaptador mientras RV está recalculando el diseño. Puede evitarlo si no llama a notifyDataSetChanged si el estado comprobado del elemento es igual al valor enviado en la devolución de llamada (que será el caso si la llamada
checkbox.setChecked
activa la devolución de llamada).fuente
Use onClickListner en la casilla de verificación en lugar de OnCheckedChangeListener, resolverá el problema
fuente
Antes de
notifyDataSetChanged()
comprobar eso con este método:recyclerView.IsComputingLayout()
fuente
Publicación de uso simple:
fuente
Me encontré con este problema exacto! Después de que la respuesta de Moonsoo realmente no hizo flotar mi bote, me equivoqué un poco y encontré una solución que funcionó para mí.
Primero, aquí hay algo de mi código:
Notarás que estoy notificando específicamente al adaptador la posición que estoy cambiando, en lugar de todo el conjunto de datos como lo estás haciendo. Dicho esto, aunque no puedo garantizar que esto funcione para usted, resolví el problema envolviendo mi
notifyItemChanged()
llamada en un bloque try / catch. ¡Esto simplemente captó la excepción, pero aún permitió que mi adaptador registrara el cambio de estado y actualizara la pantalla!¡Espero que esto ayude a alguien!
EDITAR: Admito que probablemente esta no sea la forma adecuada / madura de manejar el problema, pero dado que no parece estar causando ningún problema al dejar la excepción sin controlar, pensé que compartiría en caso de que fuera bueno suficiente para alguien más.
fuente
Esto sucede porque probablemente esté configurando el 'oyente' antes de configurar el valor para esa fila, lo que hace que el oyente se active cuando 'configura el valor' para la casilla de verificación.
Lo que debes hacer es:
fuente
fuente
simplemente use el
isPressed()
método deCompoundButton
poronCheckedChanged(CompoundButton compoundButton, boolean isChecked)
ej.
fuente
Tuve el mismo problema al usar Checkbox y RadioButton. Sustitución
notifyDataSetChanged()
pornotifyItemChanged(position)
trabajado. Agregué un campo booleanoisChecked
al modelo de datos. Luego actualicé el valor booleano y enonCheckedChangedListener
, llaménotifyItemChanged(adapterPosition)
. Puede que esta no sea la mejor manera, pero funcionó para mí. El valor booleano se usa para verificar si el elemento está marcado.fuente
la mayoría de las veces sucede porque notificar a un cambio de conjunto de datos llamando al evento de casilla de verificación cambiado y en ese caso nuevamente hay un cambio de conjunto de notificación .
para resolverlo, simplemente puede verificar que la casilla de verificación esté marcada programáticamente o que el usuario la haya presionado. Hay un método presionado para ello.
así que envuelva todo el código de lista dentro del método isPressed. Y está hecho.
fuente
Sufrí con este problema durante horas y así es como puedes solucionarlo. Pero antes de comenzar, hay algunas condiciones para esta solución.
CLASE DE MODELO
CAJA DE VERIFICACIÓN en CLASE DE ADAPTADOR
ADAPTADOR CLASE CONSTRUCTOR Y LISTA DE MODELO
ONBINDVIEW [Utilice onclick en lugar de onCheckChange]
}
fuente
Para mí, el problema ocurrió cuando salí de EditText por Listo, Atrás o toque de entrada externo. Esto hace que se actualice el modelo con el texto de entrada, luego se actualiza la vista del reciclador mediante la observación de datos en vivo.
El problema era que el cursor / foco permanecía en EditText.
Cuando he eliminado el foco usando:
El método de notificación de cambio de datos de la vista del reciclador dejó de arrojar este error.
Creo que esta es una de las posibles razones / soluciones a este problema. Es posible que esta excepción se pueda solucionar de otra manera, ya que puede ser causada por una razón totalmente diferente.
fuente