Как отобразить DialogFragment из обработчика

У меня есть обработчик, который отображает DialogFragment при получении определенного сообщения. Обычно это работает, но если фрагмент уже был сохранен, я получаю следующую ошибку:

E/AndroidRuntime (3898): НЕИСПРАВНОЕ ИСКЛЮЧЕНИЕ: main E/AndroidRuntime (3898): java.lang.IllegalStateException: невозможно выполнить это действие после onSaveInstanceState E/AndroidRuntime (3898): в android.support.v4.app.FragmentManagerImpl.checkStateLoss (FragmentManager.java:1299) E/AndroidRuntime(3898): в android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1310) E/AndroidRuntime(3898): в android.support.v4.app.BackStackRecord .commitInternal(BackStackRecord.java:541) E/AndroidRuntime(3898): в android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:525) E/AndroidRuntime(3898): в android.support.v4.app .DialogFragment.show(DialogFragment.java:123) E/AndroidRuntime(3898): в com.malauzai.app.BaseActivity$2.handleMessage(BaseActivity.java:72) E/AndroidRuntime(3898): в android.os.Handler. диспетчерское сообщение (Handler.java: 99)

Теперь я знаю, что это ожидается, основываясь на Javadoc для FragmentManager.beginTransaction:

Примечание. Транзакция фрагмента может быть создана/подтверждена только до того, как действие сохранит свое состояние. Если вы попытаетесь зафиксировать транзакцию после Activity.onSaveInstanceState() (и до следующего Activity.onStart или Activity.onResume(), вы получите сообщение об ошибке. Это связано с тем, что фреймворк заботится о сохранении ваших текущих фрагментов в состоянии , и если изменения будут внесены после сохранения состояния, то они будут утеряны.

Моя проблема в том, что я не могу сказать, как это предотвратить. Я пытался позвонить Handler.removeMessages() на onPause(), но это все еще происходит. Я пытался установить флаг в onSaveInstanceState() и не показывать фрагмент, если он установлен, но это все равно происходит. Это кажется довольно распространенной проблемой, но я не могу найти решение, которое работает. В принципе, как я узнаю, что фрагмент уже был сохранен?

Кстати, это происходит с моей BaseActivity (расширяет FragmentActivity), но у каждой активности есть свой обработчик, поэтому я не думаю, что это должно быть проблемой.

Моя последняя мысль - использовать Fragment.commitAllowingStateLoss(), но это похоже на хак.

EDIT: Вот код, который вызывает у меня проблемы:

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;
        }
      }
};

person Shawn Lauzon    schedule 02.02.2012    source источник
comment
Как правило, считается плохим пользовательским интерфейсом резко показывать диалог в случайные моменты времени, поэтому, прежде чем вы попытаетесь найти обходной путь, я бы пересмотрел ваш дизайн. См. этот сообщение в блоге< /a> об этой теме для получения дополнительной информации.   -  person Alex Lockwood    schedule 21.08.2013


Ответы (1)


В своем ответе я предполагаю, что вы используете FragmentManager и добавляете фрагменты через FragmentTransacts с тегами (или идентификаторами). так что в основном внутри вашего BaseActivity вы можете просто сделать что-то вроде этого

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
}
person Rafael T    schedule 02.02.2012
comment
Нет, фрагмент, который я пытаюсь добавить, никогда не существует. Это FragmentDialog, который создается только тогда, когда я получаю сообщение. Я добавлю немного кода. - person Shawn Lauzon; 02.02.2012
comment
Хотя я никогда не видел, чтобы эта проблема вызывала это сообщение об ошибке, вам определенно следует попробовать то, что предлагает Рафаэль. Если вы говорите, что его никогда не существовало, возможно, существовал какой-то другой диалог. Измените свой тег с dialog на this_specific_dialog - person Pedro Loureiro; 06.02.2012
comment
Превосходно. У меня было несколько разных диалогов с одним и тем же тегом. Хороший ответ/комментарий. - person Knossos; 23.05.2012