Tengo una aplicación de Android en vivo, y del mercado he recibido el siguiente seguimiento de la pila y no tengo idea de por qué está sucediendo, ya que no está sucediendo en el código de la aplicación, sino que es causado por algún u otro evento de la aplicación (supuesto)
No estoy usando Fragments, todavía hay una referencia de FragmentManager. Si algún cuerpo puede arrojar algo de luz sobre algunos hechos ocultos para evitar este tipo de problema:
java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
at android.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1109)
at android.app.FragmentManagerImpl.popBackStackImmediate(FragmentManager.java:399)
at android.app.Activity.onBackPressed(Activity.java:2066)
at android.app.Activity.onKeyDown(Activity.java:1962)
at android.view.KeyEvent.dispatch(KeyEvent.java:2482)
at android.app.Activity.dispatchKeyEvent(Activity.java:2274)
at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:1668)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1112)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1112)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1112)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1112)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1112)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1112)
at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchKeyEvent(PhoneWindow.java:1720)
at com.android.internal.policy.impl.PhoneWindow.superDispatchKeyEvent(PhoneWindow.java:1258)
at android.app.Activity.dispatchKeyEvent(Activity.java:2269)
at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:1668)
at android.view.ViewRoot.deliverKeyEventPostIme(ViewRoot.java:2851)
at android.view.ViewRoot.handleFinishedEvent(ViewRoot.java:2824)
at android.view.ViewRoot.handleMessage(ViewRoot.java:2011)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:132)
at android.app.ActivityThread.main(ActivityThread.java:4025)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:491)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:841)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:599)
at dalvik.system.NativeStart.main(Native Method)
Respuestas:
Este es el error más estúpido que he encontrado hasta ahora. Tenía una
Fragment
aplicación que trabaja perfectamente para API <11 , yForce Closing
el API> 11 .Realmente no podía entender qué cambiaron dentro del
Activity
ciclo de vida en la llamadasaveInstance
, pero aquí es cómo resolví esto:Simplemente no llamo
.super()
y todo funciona muy bien. Espero que esto te ahorre algo de tiempo.EDITAR: después de un poco más de investigación, este es un error conocido en el paquete de soporte.
Si necesita guardar la instancia y agregarle algo
outState
Bundle
, puede usar lo siguiente:EDIT2: esto también puede ocurrir si está intentando realizar una transacción después de que su
Activity
fondo haya desaparecido. Para evitar esto debes usarcommitAllowingStateLoss()
EDITAR3: Las soluciones anteriores solucionaron problemas en las primeras bibliotecas support.v4 de lo que puedo recordar. Pero si aún tiene problemas con esto, también DEBE leer el blog de @AlexLockwood : Fragment Transactions & Activity State Loss
Resumen de la publicación del blog (pero le recomiendo que lo lea):
commit()
transacciones posterioresonPause()
a Honeycomb anteriores yonStop()
posteriores a HoneycombActivity
métodos del ciclo de vida. UsoonCreate()
,onResumeFragments()
yonPostResume()
commitAllowingStateLoss()
solo como último recursofuente
commitAllowingStateLoss()
solo evita la excepción. No protege su aplicación de la pérdida accidental de estado. Ver esta publicación de blog .Al buscar en el código fuente de Android las causas de este problema, el indicador mStateSaved en
FragmentManagerImpl
clase (instancia disponible en Activity) tiene un valor verdadero. Se establece en verdadero cuando se guarda la pila posterior (saveAllState) en la llamada deActivity#onSaveInstanceState
. Luego, las llamadas de ActivityThread no restablecen este indicador utilizando los métodos de restablecimiento disponibles desdeFragmentManagerImpl#noteStateNotSaved()
ydispatch()
.A mi modo de ver, hay algunas soluciones disponibles, dependiendo de lo que esté haciendo y usando su aplicación:
Buenas maneras
Antes que nada: anunciaría el artículo de Alex Lockwood . Entonces, por lo que he hecho hasta ahora:
Para fragmentos y actividades que no necesitan mantener ninguna información de estado, llame a commitAllowStateLoss . Tomado de la documentación:
Justo después de que se confirme la transacción (que acaba de llamar
commit()
), realice una llamada aFragmentManager.executePendingTransactions()
.Formas no recomendadas:
Como Ovidiu Latcu mencionó anteriormente, no llame
super.onSaveInstanceState()
. Pero esto significa que perderá todo el estado de su actividad junto con el estado de los fragmentos.Anular
onBackPressed
y solo llamar allífinish()
. Esto debería estar bien si su aplicación no utiliza Fragments API; como ensuper.onBackPressed
hay una llamada aFragmentManager#popBackStackImmediate()
.Si está utilizando Fragments API y el estado de su actividad es importante / vital, entonces puede intentar llamar utilizando la API de reflexión
FragmentManagerImpl#noteStateNotSaved()
. Pero esto es un truco, o se podría decir que es una solución alternativa. No me gusta, pero en mi caso es bastante aceptable ya que tengo un código de una aplicación heredada que usa código obsoleto (TabActivity
e implícitamenteLocalActivityManager
).A continuación se muestra el código que utiliza la reflexión:
¡Salud!
fuente
Dicha excepción ocurrirá si intenta realizar una transición de fragmento después de que
onSaveInstanceState()
se llame a su actividad de fragmento .Una razón por la que esto puede suceder es si deja una
AsyncTask
(oThread
) en ejecución cuando se detiene una actividad.Cualquier transición posterior a la
onSaveInstanceState()
llamada podría perderse si el sistema reclama la actividad para obtener recursos y la recrea más tarde.fuente
super.onSaveInstanceState()
.Simplemente llame a super.onPostResume () antes de mostrar su fragmento o mueva su código en el método onPostResume () después de llamar a super.onPostResume (). Esto resuelve el problema!
fuente
Esto también puede suceder cuando se invoca
dismiss()
un fragmento de diálogo después de que la pantalla se ha bloqueado \ en blanco y se ha guardado el estado de instancia del diálogo Actividad +. Para evitar esta llamada:Literalmente, cada vez que descarto un cuadro de diálogo, de todos modos ya no me importa su estado, así que esto está bien, no estás perdiendo ningún estado.
fuente
Solución corta y funcional:
Siga pasos simples:
Paso 1 : anule el estado onSaveInstanceState en el fragmento respectivo. Y elimine el súper método.
Paso 2 : Use CommitAllowingStateLoss (); en lugar de commit (); mientras que las operaciones de fragmentos.
fuente
Creo que el estado del ciclo de vida puede ayudar a prevenir dicho bloqueo a partir del soporte de Android lib v26.1.0, puede hacer la siguiente verificación:
o puedes probar:
Más información aquí https://developer.android.com/reference/android/support/v4/app/Fragment.html#isStateSaved ()
fuente
esto funcionó para mí ... descubrí esto por mi cuenta ... ¡espero que te ayude!
1) NO tiene un FragmentManager / FragmentTransaction global "estático".
2) onCreate, ¡SIEMPRE inicialice el FragmentManager nuevamente!
muestra a continuación: -
fuente
Siempre recibía esto cuando intentaba mostrar fragmentos en el método onActivityForResult (), por lo que el problema era el siguiente:
Lo que hice es el siguiente:
fuente
Resolví el problema con onconfigurationchanged. El truco es que de acuerdo con el ciclo de vida de la actividad de Android, cuando explícitamente llamaste una intención (intención de la cámara o cualquier otra); la actividad se detiene y se llama a onsavedInstance en ese caso. Al girar el dispositivo a una posición diferente a la que estaba activa durante la actividad; realizar operaciones con fragmentos como la confirmación de fragmentos causa una excepción de estado ilegal. Hay muchas quejas al respecto. Es algo sobre la gestión del ciclo de vida de la actividad de Android y las llamadas a métodos adecuados. Para resolverlo, hice esto: 1-Anule el método onsavedInstance de su actividad y determine la orientación actual de la pantalla (vertical u horizontal) y luego configure la orientación de la pantalla antes de que su actividad se detenga. de esa manera la actividad bloquea la rotación de la pantalla para su actividad en caso de que haya sido rotada por otra. 2-luego, anule el método de reanudación de actividad y configure su modo de orientación ahora como sensor de modo que después de que se llame al método guardado, se llame una vez más a la configuración para manejar la rotación correctamente.
Puede copiar / pegar este código en su actividad para tratarlo:
fuente
Tuve el mismo problema, obteniendo IllegalStateException, pero reemplazar todas mis llamadas a commit () con commitAllowingStateLoss () no ayudó.
El culpable fue una llamada a DialogFragment.show ().
Lo rodeo con
y eso lo hizo OK, no puedo mostrar el diálogo, pero en este caso estuvo bien.
Era el único lugar en mi aplicación donde primero llamé a FragmentManager.beginTransaction () pero nunca llamé a commit (), así que no lo encontré cuando busqué "commit ()".
Lo curioso es que el usuario nunca abandona la aplicación. En cambio, el asesino era un anuncio intersticial de AdMob que aparecía.
fuente
Mi solución para ese problema fue
En fragmentos, agregue métodos:
Puede ser malo, pero no pudo encontrar nada mejor.
fuente
Tengo este problema, pero creo que este problema no está relacionado con commit y commitAllowStateLoss.
El siguiente mensaje de seguimiento y excepción de la pila es sobre commit ().
Pero esta excepción fue causada por onBackPressed ()
Todos fueron causados por checkStateLoss ()
mStateSaved será verdadero después de onSaveInstanceState.
Este problema rara vez ocurre. Nunca he encontrado este problema. No puedo volver a ocurrir el problema.
Encontré el problema 25517
Podría haber ocurrido en las siguientes circunstancias
La tecla de retroceso se llama después de onSaveInstanceState, pero antes de que se inicie la nueva actividad.
use onStop () en el código
No estoy seguro de cuál es la raíz del problema. Así que usé una manera fea.
fuente
Tengo el mismo problema en mi aplicación. He resuelto este problema simplemente llamando a la
super.onBackPressed();
clase anterior y llamandocommitAllowingStateLoss()
a la clase actual con ese fragmento.fuente
commitAllowingStateLoss()
lugar decommit()
Se llamará a onSaveInstance si un usuario gira la pantalla para que pueda cargar los recursos asociados con la nueva orientación.
Es posible que este usuario gire la pantalla seguido de presionar el botón Atrás (porque también es posible que este usuario haya perdido su teléfono mientras usa su aplicación)
fuente
Lea http://chris-alexander.co.uk/on-engineering/dev/android-fragments-within-fragments/
artículo. La comprobación de fragment.isResumed () me ayuda en onDestroyView sin usar el método onSaveInstanceState.
fuente
Mismo problema mío y después de un día de análisis de todos los artículos, blog y stackoverflow, encontré una solución simple. No use salvadoInstanceState en absoluto, esta es la condición con una línea de código. En el código de fragmento:
fuente
Esto sucede cada vez que intenta cargar un fragmento, pero la actividad ha cambiado su estado a onPause (). Esto sucede, por ejemplo, cuando intenta obtener datos y cargarlos en la actividad, pero cuando el usuario hace clic en algún botón y tiene movido a la siguiente actividad.
Puedes resolver esto de dos maneras
Puede usar transacción.commitAllowingStateLoss () en lugar de transacción.commit () para cargar el fragmento, pero puede terminar perdiendo la operación de confirmación que se realiza.
o
Asegúrese de que la actividad se reanude y no se detenga cuando cargue un fragmento. Cree un booleano y verifique si la actividad no va al estado onPause ().
luego, mientras carga el fragmento, verifique si hay actividad presente y cargue solo cuando la actividad esté en primer plano.
fuente
Gracias @gunar, pero creo que hay una mejor manera.
Según el documento:
Entonces use
commitNow
para reemplazar:fuente
Bueno, después de probar todas las soluciones anteriores sin éxito (porque básicamente no tengo transacciones).
En mi caso, estaba usando AlertDialogs y ProgressDialog como fragmentos que, a veces, en la rotación, al solicitar el FragmentManager, el error aumenta.
Encontré una solución alternativa mezclando muchas publicaciones similares:
Es una solución de 3 pasos, todo hecho en su FragmentActivity (en este caso, se llama GenericActivity):
fuente
Cuando uso startactivity en un fragmento, obtendré esta excepción;
Cuando cambio para usar startactivityforresult, la excepción se ha ido :)
Entonces, la forma fácil de solucionarlo es usar la API startActivityForResult :)
fuente
Obtuve esta excepción cuando presioné el botón Atrás para cancelar el selector de intención en mi actividad de fragmento de mapa. Resolví esto reemplazando el código de onResume () (donde estaba inicializando el fragmento y confirmando la transacción) por onStart () y la aplicación está funcionando bien ahora. Espero eso ayude.
fuente
Esto se soluciona en Android 4.2 y también en la fuente de la biblioteca de soporte. [*]
Para obtener detalles sobre la causa (y las soluciones), consulte el informe de errores de Google: http://code.google.com/p/android/issues/detail?id=19917
Si está utilizando la biblioteca de soporte, no debería preocuparse por este error (por mucho tiempo) [*]. Sin embargo, si está utilizando la API directamente (es decir, no está utilizando el FragmentManager de la biblioteca de soporte) y apunta a una API por debajo de Android 4.2, deberá probar una de las soluciones alternativas.
[*] Al momento de escribir esto, Android SDK Manager todavía está distribuyendo una versión anterior que exhibe este error.
Editar Voy a agregar algunas aclaraciones aquí porque obviamente de alguna manera he confundido a quien rechazó esta respuesta.
Hay varias circunstancias diferentes (pero relacionadas) que pueden hacer que se produzca esta excepción . Mi respuesta anterior se refiere a la instancia específica discutida en la pregunta, es decir, un error en Android que posteriormente se ha solucionado. Si obtiene esta excepción por otra razón, es porque está agregando / eliminando fragmentos cuando no debería (después de que se hayan guardado los estados de fragmento). Si se encuentra en una situación así, quizás " Fragmentos anidados - IllegalStateException" No se puede realizar esta acción después de onSaveInstanceState " " puede serle útil.
fuente
Después de investigar un poco, la solución a este problema es hacer sus confirmaciones de fragmentos en el resumen.
Fuente: https://wenchaojames.wordpress.com/2013/01/12/illegalstateexception-from-onactivityresult/
fuente
Mi caso de uso: he usado un oyente en fragmentos para notificar a la actividad que algo sucedió. Hice un nuevo compromiso de fragmento en el método de devolución de llamada. Esto funciona perfectamente bien la primera vez. Pero en el cambio de orientación, la actividad se recrea con el estado de instancia guardado. En ese caso, el fragmento no se crea de nuevo implica que el fragmento tiene el oyente, que es la actividad destruida. De cualquier forma, el método de devolución de llamada se activará en la acción. Va a la actividad destruida que causa el problema. La solución es restablecer el oyente en fragmentos con la actividad en vivo actual. Esto resuelve el problema.
fuente
Lo que encontré es que si otra aplicación es del tipo de diálogo y permite enviar toques a la aplicación de fondo, casi cualquier aplicación de fondo se bloqueará con este error. Creo que debemos verificar cada vez que se realiza una transacción si la instancia se guardó o restauró.
fuente
En mi caso, con la misma excepción de error, puse el "onBackPressed ()" en un archivo ejecutable (puede usar cualquiera de sus vistas):
No entiendo por qué, ¡pero funciona!
fuente
Puede estar llamando a fragmentManager.popBackStackImmediate (); cuando la actividad está en pausa. La actividad no está terminada pero está en pausa y no está en primer plano. Debe verificar si la actividad está en pausa o no antes de popBackStackImmediate ().
fuente
Noté algo muy interesante. Tengo en mi aplicación la opción de abrir la galería del teléfono y el dispositivo pregunta qué aplicación usar, allí hago clic en el área gris fuera del cuadro de diálogo y veo este problema. Noté cómo mi actividad va de onPause, onSaveInstanceState a onResume, no sucede que visite onCreateView. Estoy haciendo transacciones en onResume. Entonces, lo que terminé haciendo es configurar una marca que se niega en Pausa, pero que es verdadera en Crear Vista. si el indicador es verdadero en Resume, entonces haga onCommit, de lo contrario commitAllowingStateLoss. Podría seguir y perder mucho tiempo, pero quería comprobar el ciclo de vida. Tengo un dispositivo que es sdkversion 23, y no tengo este problema, pero tengo otro que es 21, y ahí lo veo.
fuente
puedes usar FragmentActivity.onStart antes de popBackStackImmediate
Me gusta esto:
http://jorryliu.blogspot.com/2014/09/illegalstateexception-can-not-perform.html
fuente