tutorial studio navegar implement how fragments example entre ejemplo java android android-fragments

java - implement - navegar entre fragments android studio



Acciones en onActivityResult y "Error no se puede realizar esta acción después de onSaveInstanceState" (7)

Al implementar una aplicación donde el usuario puede iniciar sesión, tengo la siguiente situación: Si el usuario está conectado, realice la acción, de lo contrario, inicie la actividad de inicio de sesión para obtener el resultado y si el resultado es Activity.RESULT_OK, realice la acción.

Mi problema es que la acción para realizar es mostrar un DialogFragment, pero llamar

DialogFragment newFragment = MyDialogFragment.newInstance(mStackLevel); newFragment.show(ft, "dialog")

en la devolución de llamada onActivityResult arroja una excepción:

Caused by: java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState

Entonces, ¿cómo puedo resolver esto? Estoy pensando en levantar una bandera allí y mostrar el diálogo en el onResume, pero veo esta solución un poco sucia

Editar: se agregó más código (estoy siguiendo este ejemplo para mostrar el DialogFragment

Cuando el usuario solicita la acción:

... if (!user.isLogged()){ startActivityForResult(new Intent(cnt, Login.class), REQUEST_LOGIN_FOR_COMMENT); }

En el mismo fragmento

@Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == REQUEST_LOGIN_FOR_COMMENT && resultCode == Activity.RESULT_OK) { FragmentTransaction ft = getFragmentManager().beginTransaction(); DialogFragment newFragment = MyDialogFragment.newInstance(); newFragment.show(ft, "dialog") } }

Y si el usuario inicia sesión en las llamadas de actividad de inicio de sesión;

setResult(Activity.RESULT_OK); finish();


Anular la función de show(Fragment manager, String tag) con permitir perder y cambiar el estado mDismissed = false; mShownByMe = true; desde la función origibal por reflexión:

public class DialogParent extends DialogFragment { @Override public void show(FragmentManager manager, String tag) { try { Field mDismissed = DialogFragment.class.getDeclaredField("mDismissed"); Field mShownByMe = DialogFragment.class.getDeclaredField("mShownByMe"); mDismissed.setAccessible(true); mShownByMe.setAccessible(true); mDismissed.setBoolean(this, false); mShownByMe.setBoolean(this, true); } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } FragmentTransaction ft = manager.beginTransaction(); ft.add(this, tag); ft.commitAllowingStateLoss(); } }


Aquí está la solución alternativa que funciona bien para mí.

private void alert(final String message) { Handler handler = new Handler(Looper.getMainLooper()); handler.post(new Runnable() { public void run() { AlertDialogFragment alertDialogFragment = AlertDialogFragment.newInstance(message); alertDialogFragment.show(getFragmentManager(), ALERT_DIALOG_FRAGMENT); } }); }


Esta excepción se produce siempre que se compromete FragmentManager después de que FragmentManager haya guardado su estado. La manera fácil y limpia es verificar si FragmentManager ya ha guardado el estado antes de mostrar un DialogFragment .

if(!getSupportFragmentManager.isStateSaved()) { MyDialogFragment dialogFragment = new MyDialogFragment() dialogFragment.show(getSupportFragmentManager, TAG); }


Esto realmente funciona.

CheckinSuccessDialog dialog = new CheckinSuccessDialog(); //dialog.show(getSupportFragmentManager(), null); FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); ft.add(dialog, null); ft.commitAllowingStateLoss();

Pero aún así es malo, porque obtuve el error "La actividad se ha destruido"

ava.lang.IllegalStateException: Activity has been destroyed fragmentTransaction.commitAllowingStateLoss();

Entonces mi solución es agregar verificación if (!isFinishing()&&!isDestroyed())

CheckinSuccessDialog fragment = CheckinSuccessDialog.newInstance(); if (fragment instanceof DialogFragment) { DialogFragment dialog = (DialogFragment) fragment; if (!dialog.isAdded()) { fragmentTransaction.add(dialog, CheckinSuccessDialog.class.getName()); if (!isFinishing()&&!isDestroyed()) { fragmentTransaction.commitAllowingStateLoss(); } }

en despedir:

FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction(); Fragment fragment = getSupportFragmentManager().findFragmentByTag(CheckinSuccessDialog.class.getName()); if (fragment != null && fragment instanceof DialogFragment) { DialogFragment dialog = (DialogFragment) fragment; dialog.dismiss(); if (!isFinishing()&&!isDestroyed()) { fragmentTransaction.commitAllowingStateLoss(); } }


Lo mejor que he pensado es no usar .show () sino hacer esto.

CheckinSuccessDialog dialog = new CheckinSuccessDialog(); //dialog.show(getSupportFragmentManager(), null); FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); ft.add(dialog, null); ft.commitAllowingStateLoss();


Si utilizo un DialogFragment, lo único que funcionó para mí fue descartar el Fragment con dissmissAllowingStateLoss ()


Simplemente compruebo si una actividad está siendo destruida.

if (!getActivity().isFinishing()) { DialogFragment fragment = MyFragment.newInstance(); fragment.show(getActivity().getSupportFragmentManager(), MyFragment.TAG); }