DialogFrag # show () de un lanzamiento de fragmentos "IllegalStateException: no se puede realizar esta acción después onSaveInstanceState"
Sólo para ser claro, he leído la docena de preguntas más importantes sobre "IllegalStateException: No se puede realizar esta acción después de onSaveInstanceState" y he leído el blog de Alex Lockwood sobre el tema http://www.androiddesignpatterns.com/2013/08/ Fragment-transaction-commit-state-loss.html
Así que no estoy pidiendo esto ciegamente.
- DatePickerDialog onDateSet llamado cuando se gira
- ¿Cómo tratar los datos retenidos después de que la actividad llegue a primer plano cuando se utiliza más de una actividad?
- Realizar una pausa de actividad que no se reanuda después de volver a crear el método
- Android: onPostResume se llama después de que se reanude el fragmento
- Actividad con servicio duradero en el fondo que no se matará
Tengo un caso de uso muy simple caso que no implica AsyncTask o cualquier procesamiento en segundo plano.
Tengo un fragmento que contiene un botón. En el onClickListener para el botón, crear un DialogFragment y mostrarlo.
public final class OverviewFragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { final View view = inflater.inflate(R.layout.overview_fragment, container, false); startNewGameButton = (Button) view.findViewById(R.id.buttonNewGame); startNewGameButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { final NewGameFragment dialogFrag = NewGameFragment.create(getApplication()); dialogFrag.show(getFragmentManager(), NewGameFragment.FRAGMENT_TAG); } }); }
[NewGameFragment]
public final class NewGameFragment extends DialogFragment { public static final String FRAGMENT_TAG = "NewGameFragment"; private static final String MESSAGE = "message"; public static NewGameFragment create(Context context) { final AppsPreferences prefs = new AppPreferences(context); final int startOption = prefs.getGameStartOption(); final Bundle bundle = new Bundle(); bundle.putString(MESSAGE, getMessage(context, startOption)); final NewGameFragment fragment = new NewGameFragment(); fragment.setArguments(bundle); return fragment; } @Override public final Dialog onCreateDialog(Bundle savedInstanceState) { final String message = getArguments().getString(MESSAGE); final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()) .setTitle(R.string.progress_startGame_title) .setMessage(message); builder.setPositiveButton(R.string.progress_startGame_raceButton, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { new RaceAction().execute(); } }); builder.setNegativeButton(R.string.progress_startGame_eventButton, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { new EventAction().execute(); } }); final Dialog dialog = builder.create(); dialog.setCanceledOnTouchOutside(false); // Whether clicking outside the dialog closes the dialog. return dialog; } }
[Stacktrace]
java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState at android.support.v4.app.FragmentManagerImpl.void checkStateLoss()(SourceFile:1365) at android.support.v4.app.FragmentManagerImpl.void enqueueAction(java.lang.Runnable,boolean)(SourceFile:1383) at android.support.v4.app.BackStackRecord.int commitInternal(boolean)(SourceFile:636) at android.support.v4.app.BackStackRecord.int commit()(SourceFile:615) at android.support.v4.app.DialogFragment.void show(android.support.v4.app.FragmentManager,java.lang.String)(SourceFile:138) at au.com.xandar.thegame.overview.OverviewFragment$1.void onClick(android.view.View)(SourceFile:160) at android.view.View.performClick(View.java:4162) at android.view.View$PerformClick.run(View.java:17082) at android.os.Handler.handleCallback(Handler.java:615) at android.os.Handler.dispatchMessage(Handler.java:92) at android.os.Looper.loop(Looper.java:137) at android.app.ActivityThread.main(ActivityThread.java:4867) 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:1007) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:774) at dalvik.system.NativeStart.main(Native Method)
Nota: el Fragmento y el DialogFragment vienen ambos de support-v4: 21.0.0
Estoy viendo esto en una gama de dispositivos que ejecutan 4.4. Pero al menos una instancia se ha producido en un Nexus 7 que ejecuta 5.0.
No he sido capaz de replicar esto yo mismo. Ni siquiera mediante la introducción de un retraso artificial en el onClick y el intento de rotar, volver, el hogar de la aplicación.
Así que desde FragmentTransaction
(para DialogFrag#show()
) se está creando y comprometido en el subproceso de interfaz de usuario directamente desde onClick()
, ¿cómo puede el Fragment
ya ha pasado onSaveInstanceState()
?
¿Significa que necesito comprobar el estado del Ciclo de Vida de la Actividad al inicio de cada entrada del usuario? – muy malo (el ciclo de vida está destinado a ser el manejo de que para mí No debería recibir la entrada del usuario si la actividad ya ha pasado onPause()
)
¿Significa que necesito comprobar el estado del ciclo de vida de la actividad antes de cada sentencia durante la ejecución de la entrada del usuario? – mal roto!
¿Qué puedo hacer para evitar que esto ocurra?
Informacion adicional:
Después de correr en la naturaleza durante varios días puedo decir categóricamente que getChildFragmentManager()
no es la solución.
Se produce un error en las siguientes versiones de Android:
- 4.4.2 90%
- 4.4.4 5%
- 5,0 5%
- Distinguir entre presionar el botón "inicio" y abrir otra Actividad
- OnCreate () vs OnStart ()
- Cómo "destruir" varias actividades de Android al mismo tiempo
- Cuándo llamar a super.onPause ()?
- ¿Qué sucede con la aplicación Android cuando una llamada telefónica interrumpe la aplicación?
- ¿Cómo puedo comprobar en Robotium que la aplicación ha terminado?
- Cómo administrar el estado de la interfaz de usuario y la pila posterior en un diseño de panel único / dual
- Comportamiento extraño del ciclo de vida de la actividad - después onResume () también onPause () llamado ... ¿por qué?
OK, por lo que puedo decir esto es un error en el AOSP, ya que también he visto una instancia de esto de pura pila de Android (es decir, nada de mi código en absoluto).
Por lo tanto, parece que existe un problema de subprocesamiento en el ciclo de vida de Actividad / Fragmento en el que un hilo de interfaz de usuario puede obtener prioridad para responder a un clic de botón DESPUÉS de que la Actividad / Fragmento ya haya guardado su estado.
Mi trabajo en torno al cual ha sido 100% exitoso hasta ahora es capturar la IllegalStateException y programar el cuadro de diálogo mostrar para la próxima vez que la Actividad / Fragmento se activa con un PauseHandler https://stackoverflow.com/a/25322330/493682
- La notificación de pantalla completa solo se muestra como un Heads Up
- Escucha tocar y arrastrar el valor y la función en consecuencia