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.

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%

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

  • ¿Por qué OnCreate () de Fragment se llama a veces antes de OnCreate de Activity ()?
  • ¿Cuál es el fragmento equivalente de Activity.isFinishing ()?
  • Documentación de la clase de aplicación Android lifecyle
  • ¿Por qué se definen los métodos del ciclo de vida en la clase de actividad con el especificador de acceso protegido
  • Ciclo de vida del fragmento AppCompat cambiado
  • NsdManager no detiene el descubrimiento de servicio
  • IllegalStateException: Fragmento ya agregado en el fragmento tabhost
  • Los miembros de la clase en Fragmento se convierten en nulos después de pulsar el botón Inicio y esperar
  • Guardar el estado cuando se pulsa el botón Atrás
  • Ciclo de vida de BroadcastReceiver
  • Android: Cuando se cancela un servicio, ¿cómo podemos persistir el estado del servicio para una restauración posterior?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.