Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to display a DialogFragment from a Handler

I have a Handler which displays a DialogFragment when it receives a particular message. This usually works, but if the fragment has already been saved, I get the following error:

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)

Now, I know that this is expected, based on the Javadoc for 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.

My problem is that I can't tell how to prevent it. I've tried calling Handler.removeMessages() on onPause(), but it still occurs. I've tried setting a flag in onSaveInstanceState() and not showing the fragment if it's set, but it still occurs. This seems like a pretty common problem, but I can't come up with a solution that works. Basically, how do I know that the fragment has already been saved?

BTW, this occurs on my BaseActivity (extends FragmentActivity), but each activity has its own handler, so I don't think this should be an issue.

My last thought is using Fragment.commitAllowingStateLoss(), but that seems like a hack.

EDIT: Here's the code that's causing me problems:

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;
        }
      }
};
like image 717
Shawn Lauzon Avatar asked Nov 13 '22 10:11

Shawn Lauzon


1 Answers

I assume in my answer that you are using FragmentManager and add Fragments through FragmentTransacts with tags (or ids). so basically inside your BaseActivity you could just do something like this

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
}
like image 77
Rafael T Avatar answered Nov 16 '22 04:11

Rafael T