2012-08-24 12 views
42

la implementación de una aplicación donde el usuario puede iniciar sesión en la que tengo la siguiente situación: Si se registra el usuario en realizar la acción demás iniciar la actividad de inicio de sesión para el resultado y si el resultado es Activity.RESULT_OK realizar la acción.acciones en onActivityResult y "Error No se puede realizar esta acción después de onSaveInstanceState"

Mi problema es que la acción debe jugar es mostrar un DialogFragment, pero llamar

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

en la devolución de llamada onActivityResult se emite una excepción:

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

Entonces, ¿cómo puedo solucionar esto? Estoy pensando en elevar una bandera allí y mostrar el cuadro de diálogo en el onResume pero veo esta solución un poco sucio

Editar: Se ha añadido más código (Im siguiendo este ejemplo para mostrar la DialogFragment

Cuando la acción es solicitados por el usuario:

... 
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 la actividad de sesión llamadas;

setResult(Activity.RESULT_OK); 
finish(); 
+0

creo que deberías publicar todo el código. Parece que está tratando de mostrar el diálogo después de onpause – nandeesh

+0

Editó la pregunta: D – Addev

+1

Compruebe http://www.androiddesignpatterns.com/2013/08/fragment-transaction-commit-state-loss.html para comprender por qué esto está sucediendo – Maragues

Respuesta

94

Lo mejor que se me ocurre 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(); 
+2

Aunque me funciona, me siento inseguro porque dejamos fuera 2 variables: mDismissed = false; mShownByMe = verdadero; Las variables anteriores se están modificando en la función show original. –

+2

gracias, commitAllowingStateLoss resolvió el problema –

+0

mDismissed y mShowByMe parecen ser variables específicamente para rastrear si el diálogo fue mostrado/oculto por llamadas externas. En otras palabras, compensan exactamente este tipo de cosas. –

9

Aquí está la solución 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); 
     } 
    });   
} 
4

Si se utiliza un DialogFragment, lo único que trabajó para mí fue despedir el fragmento con dissmissAllowingStateLoss()

3

simplemente comprobar si se está destruyendo una actividad.

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

Anulación show(Fragment manager, String tag) función con lo que pierde el estado y cambiar mDismissed = false;mShownByMe = true; de la función origibal por la 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(); 
    } 
} 
+0

También podría rodear el método show de los padres con un try-catch, donde en la captura agregue el diálogo y use su transacción llamando 'commitAllowingStateLoss()'. De esta manera no necesitas ningún reflejo. – SimonSimCity

0

Este reales obras.

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

Pero, pero sigue siendo malo, porque ha obtenido un error “La actividad ha sido destruido”

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

Así que mi solución es añadir comprobar 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(); 
      } 
     } 
0

Esta excepción es t hrown cada vez que un FragmentTrasaction está confiado después FragmentManager ha salvado su estado.La manera fácil y limpia es verificar si FragmentManager ya ha guardado el estado antes de mostrar DialogFragment.

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