Android – java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState with DialogFragment

androidandroid-dialogfragmentandroid-support-libraryillegalstateexception

I am facing issue with DialogFragment / getSupportFragmentManager / Android version 4.x

01-10 19:46:48.228: E/AndroidRuntime(9879): java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
01-10 19:46:48.228: E/AndroidRuntime(9879):     at android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1314)
01-10 19:46:48.228: E/AndroidRuntime(9879):     at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1325)
01-10 19:46:48.228: E/AndroidRuntime(9879):     at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:548)
01-10 19:46:48.228: E/AndroidRuntime(9879):     at android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:532)
01-10 19:46:48.228: E/AndroidRuntime(9879):     at android.support.v4.app.DialogFragment.show(DialogFragment.java:127)
01-10 19:46:48.228: E/AndroidRuntime(9879):     at com.v1.mypck.TermsAndConditions.showDialog(TermsAndConditions.java:256)
01-10 19:46:48.228: E/AndroidRuntime(9879):     at com.v1.mypck.TermsAndConditions.handleMessage(TermsAndConditions.java:62)
01-10 19:46:48.228: E/AndroidRuntime(9879):     at com.v1.mypck.TermsAndConditions$IncomingHandler.handleMessage(TermsAndConditions.java:53)
01-10 19:46:48.228: E/AndroidRuntime(9879):     at android.os.Handler.dispatchMessage(Handler.java:99)
01-10 19:46:48.228: E/AndroidRuntime(9879):     at android.os.Looper.loop(Looper.java:137)
01-10 19:46:48.228: E/AndroidRuntime(9879):     at android.app.ActivityThread.main(ActivityThread.java:4441)
01-10 19:46:48.228: E/AndroidRuntime(9879):     at java.lang.reflect.Method.invokeNative(Native Method)
01-10 19:46:48.228: E/AndroidRuntime(9879):     at java.lang.reflect.Method.invoke(Method.java:511)
01-10 19:46:48.228: E/AndroidRuntime(9879):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
01-10 19:46:48.228: E/AndroidRuntime(9879):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
01-10 19:46:48.228: E/AndroidRuntime(9879):     at dalvik.system.NativeStart.main(Native Method)

In below code when i press back it tries to finish current activity and go back to previous activity it throws above error.

Code works well on older version (prior to 4.x).

Can somebody guide me in right direction.

public class TermsAndConditions extends SherlockFragmentActivity implements LoaderManager.LoaderCallbacks<JSONObject>{
    static final String TAG = "TermsAndConditions";
    private static int titleResource;
    private static int messageResource;

    private IncomingHandler handler = null;
    private static final int SHOW_NETWORK_DIALOG = 3;

    static class IncomingHandler extends Handler {
        private final WeakReference<TermsAndConditions> mTarget; 

        IncomingHandler(TermsAndConditions target) {
            mTarget = new WeakReference<TermsAndConditions>(target);
        }

        @Override
        public void handleMessage(Message msg) {
            TermsAndConditions target = mTarget.get();
            if (target != null) {
                target.handleMessage(msg);
            }
        }
    }
    public void handleMessage(Message msg) {
        switch (msg.what)  {
            case SHOW_NETWORK_DIALOG:
                titleResource = R.string.msg_alert_no_network_title;
                messageResource = R.string.msg_alert_no_network_message;
                showDialog();
                break;
        }
    }
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.web_view);

        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        getSupportLoaderManager().initLoader(0, null, this);
    }
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home:
                finish();
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }
    private void loadViewData() {
        //Logic to load content.
    }

    @Override
    public Loader<JSONObject> onCreateLoader(int arg0, Bundle arg1) {
        if (handler == null){
            handler = new IncomingHandler(TermsAndConditions.this);
        }
        return new JsonLoader(this);
    }

    @Override
    public void onLoadFinished(Loader<JSONObject> arg0, JSONObject jsonData) {
        if(jsonDataObject==null || jsonDataObject.length()==0) {
            handler.sendEmptyMessage(SHOW_NETWORK_DIALOG);
        } else {
            loadViewData();
        }
    }

    @Override
    public void onLoaderReset(Loader<JSONObject> arg0) {
        if(jsonDataObject==null || jsonDataObject.length()==0) {
            handler.sendEmptyMessage(SHOW_NETWORK_DIALOG);
        } else {
            loadViewData();
        }
    }

    public static class JsonLoader extends AsyncTaskLoader<JSONObject> {
        public JsonLoader(Context context) {
            super(context);
        }

        @Override 
        protected void onStartLoading() {
            if (jsonDataObject != null) {
                deliverResult(jsonDataObject);
            }
            if (takeContentChanged() || jsonDataObject == null) {
                forceLoad();
            }
        }

        @Override
        public JSONObject loadInBackground() {
            try {
                return response.getJSONObject("result");
            } catch (JSONException e) {
                return null;
            } catch (Throwable e) {
                return null;
            }
        }

        @Override 
        public void deliverResult(JSONObject newJsonData) {
            if (isReset()) {
                if (jsonDataObject != null) {
                    onReleaseResources(jsonDataObject);
                }
            }
            JSONObject oldData = jsonDataObject;
            jsonDataObject = newJsonData;
            if (isStarted()) {
                super.deliverResult(jsonDataObject);
            }
            if (oldData != null) {
                onReleaseResources(oldData);
            }
        }

        @Override 
        protected void onStopLoading() {
            cancelLoad();
        }

        @Override public void onCanceled(JSONObject jsonData) {
            super.onCanceled(jsonData);
            onReleaseResources(jsonData);
        }

        @Override protected void onReset() {
            super.onReset();
            onStopLoading();
            if (jsonDataObject != null) {
                onReleaseResources(jsonDataObject);
                jsonDataObject = null;
            }
        }

        protected void onReleaseResources(JSONObject jsonData) {
            jsonData = null;
        }
    }
    public static class MyAlertDialogFragment extends DialogFragment {
        public static MyAlertDialogFragment newInstance(int title) {
            MyAlertDialogFragment frag = new MyAlertDialogFragment();
            Bundle args = new Bundle();
            args.putInt("title", title);
            frag.setArguments(args);
            return frag;
        }

        @Override
        public Dialog onCreateDialog(Bundle savedInstanceState) {
            int title = getArguments().getInt("title");
            return new AlertDialog.Builder(getActivity())
                    .setTitle(title)
                    .setMessage(messageResource)
                    .setPositiveButton(R.string.alert_dialog_ok,
                        new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int whichButton) {

                            }
                        }
                    )
                    .create();
        }
    }
    public void showDialog() {
        DialogFragment newFragment = MyAlertDialogFragment.newInstance(titleResource);
        newFragment.show(getSupportFragmentManager(), "my_dialog");
    }
}

Best Answer

Here is the answer in another thread:

Actions in onActivityResult and "Error Can not perform this action after onSaveInstanceState"

also here:

Refreshing my fragment not working like I thought it should

This is an example solving this problem:

DialogFragment loadingDialog = createDialog();

FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
                    transaction.add(loadingDialog, "loading");
                    transaction.commitAllowingStateLoss();