5

Mam Handler, który wyświetla DialogFragment po otrzymaniu określonej wiadomości. To zazwyczaj działa, ale jeśli fragment został już zapisany, pojawia się następujący błąd:Jak wyświetlić DialogFragment z Handler'a

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)

Teraz wiem, że to jest z oczekiwaniami, na podstawie Javadoc dla 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.

Moim problemem jest to, że nie umiem tego powstrzymać. Próbowałem wywoływać Handler.removeMessages() na onPause(), ale nadal występuje. Próbowałem ustawić flagę w onSaveInstanceState() i nie pokazano fragmentu, jeśli jest ustawiony, ale nadal występuje. Wydaje się, że jest to dość powszechny problem, ale nie mogę wymyślić rozwiązania, które działa. Zasadniczo, skąd mam wiedzieć, że fragment został już zapisany?

BTW, to zdarza się na mojej BaseActivity (rozszerza FragmentActivity), ale każde działanie ma swój własny handler, więc nie sądzę, że to powinien być problem.

Moja ostatnia myśl jest przy użyciu Fragment.commitAllowingStateLoss(), ale to wygląda jak włamanie.

EDIT: Oto kod, który jest przyczyną mnie problemów:

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

Generalnie uważa się za złe doświadczenia użytkownika, aby wyświetlić okno dialogowe nagle w przypadkowych chwilach takich jak ta, więc zanim spróbujesz trudno znaleźć pracę wokół , Przemyślałbym twój projekt. Więcej informacji na ten temat można znaleźć w [** postach na blogu **] (http://www.androiddesignpatterns.com/2013/08/fragment-transaction-commit-state-loss.html). –

Odpowiedz

1

zakładam w moją odpowiedź, że używasz FragmentManager i dodać Fragments przez FragmentTransacts ze znacznikami (lub ID). więc w zasadzie wewnątrz BaseActivity można po prostu zrobić coś takiego

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

Nie, fragment, który próbuję dodać, nigdy nie istnieje. Jest to FragmentDialog, który jest tworzony tylko wtedy, gdy otrzymam wiadomość. Dodam kod. –

+2

Chociaż nigdy nie widziałem problemu powodującego ten komunikat o błędzie, zdecydowanie powinieneś spróbować tego, co sugeruje Rafael. Jeśli powiesz "nigdy nie istnieje", być może istniał inny dialog. Zmień swój tag z "okna dialogowego" na "ten_specyficzny_dialog". –

+0

Doskonały. Miałem kilka różnych okien dialogowych z tym samym tagiem. Dobra odpowiedź/komentarz. – Knossos

Powiązane problemy