5

Ho un gestore che visualizza un DialogFragment quando riceve un messaggio particolare. Questo di solito funziona, ma se il frammento è già stato salvato, ottengo il seguente errore:Come visualizzare un DialogFragment da un gestore

E/AndroidRuntime(3898): FATAL EXCEPTION: main E/AndroidRuntime(3898): java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState E/AndroidRuntime(3898): at android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1299) E/AndroidRuntime(3898): at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1310) E/AndroidRuntime(3898): at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:541) E/AndroidRuntime(3898): at android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:525) E/AndroidRuntime(3898): at android.support.v4.app.DialogFragment.show(DialogFragment.java:123) E/AndroidRuntime(3898): at com.malauzai.app.BaseActivity$2.handleMessage(BaseActivity.java:72) E/AndroidRuntime(3898): at android.os.Handler.dispatchMessage(Handler.java:99)

Ora, so che questo è previsto, sulla base del Javadoc per FragmentManager.beginTransaction:

Note: A fragment transaction can only be created/committed prior to an activity saving its state. If you try to commit a transaction after Activity.onSaveInstanceState() (and prior to a following Activity.onStart or Activity.onResume(), you will get an error. This is because the framework takes care of saving your current fragments in the state, and if changes are made after the state is saved then they will be lost.

Il mio problema è che non posso dire come prevenirlo. Ho provato a chiamare Handler.removeMessages() su onPause(), ma si verifica ancora. Ho provato a impostare un flag in onSaveInstanceState() e non mostrare il frammento se è impostato, ma si verifica ancora. Questo sembra un problema abbastanza comune, ma non riesco a trovare una soluzione che funzioni. In sostanza, come faccio a sapere se il frammento è già stato salvato?

BTW, questo si verifica sul mio BaseActivity (estende FragmentActivity), ma ogni attività ha il proprio gestore, quindi non penso che questo dovrebbe essere un problema.

Il mio ultimo pensiero utilizza Fragment.commitAllowingStateLoss(), ma sembra un trucco.

EDIT: Ecco il codice che mi sta causando problemi:

private final Handler mTimerHandler = new Handler() { 
     @Override 
     public void handleMessage(Message msg) { 
     switch (msg.what) { 
     case TIMER_MESSAGE_LOGOUT_WARNING: 
      // throws IllegalStateException if fragment is already saved 
      new LogoutWarningDialog().show(getSupportFragmentManager(), 
        "dialog"); 
      break; 
     } 
     } 
}; 
+0

Generalmente è considerato come l'esperienza dell'utente male a mostrare una finestra di dialogo bruscamente a volte casuali come questo, quindi prima si tenta di difficile trovare un lavoro in giro , Riconsidererei il tuo design. Vedi questo [** blog post **] (http://www.androiddesignpatterns.com/2013/08/fragment-transaction-commit-state-loss.html) su questo argomento per ulteriori informazioni. –

risposta

1

presumo nella mia risposta che si sta utilizzando FragmentManager e aggiungere Frammenti attraverso FragmentTransacts con tag (o ID). Quindi, in pratica all'interno del vostro BaseActivity si può solo fare qualcosa di simile

FragmentManager manager = getFragmentSupportedManager(); 
Fragment fragmentIWannaKnowIfexists = manager.findFragmentByTag("Tag I used to create this Fragment inside FragmentTrasnsaction") 
// or manager.findFragmentById(ID_FROM_LAYOUT) 
if(fragmentIWannaKnowIfexists != null){ 
    //we have this Fragment already 
} else { 
    // this Fragment was not added already 
} 
+0

No, il frammento che sto tentando di aggiungere non esiste mai. È un FragmentDialog che viene creato solo quando ottengo il messaggio. Aggiungerò del codice. –

+2

Anche se non ho mai visto questo problema a causare questo messaggio di errore, dovresti assolutamente provare cosa suggerisce Rafael. Se dici "non esiste mai", forse esisteva un altro dialogo. Cambia il tuo tag da "dialog" a "this_specific_dialog" –

+0

Eccellente. Ho avuto un paio di finestre di dialogo diverse con lo stesso tag. Buona risposta/commento – Knossos

Problemi correlati