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");
}
}
Probably, the handler that is responding to the HandleMessage is associated to a destroyed activity.
i.e.: If you rotate the screen, the old destroyed activity will handle the message, then you will call showDialog, and the exception will be thrown:
You are creating a dialog after the old destroyed activity has called his onSaveInstanceState.
Try replacing the callback, with the new created activity, to make sure that you are creating the dialog always in the alive activity.
If you are not rotating, put a flag on onSaveInstance like "saving", and disabling it on onRestoreInstance. In your handleMessage method, if the flag "saving" is on, don't show the dialog, just turn on another flag indicating that the dialog must be created on onResume. Then on onResume method, check if in middle of that process, you should create the dialog, if yes, show it on onResume method.
too late answer but may be the correct answer. I made a parent class and and dialog fragment extends from it
}
onPostResume() use post resume method to do your work.. I think you are calling show dialog method in onRestart or onResume, so avoid it and use onPostResume() to show your dialog.
The goal of post() method in this case is to wait while onResume() of Activity or Fragment will finished. It works if you want to show DialogFragment from Fragment., f.e. when you want to show your dialog after a system dialog dismissed.
It works:
But but still bad, because got error “Activity has been destroyed”
So my solution is add check
if (!isFinishing()&&!isDestroyed())
on dismiss:
In the Activity, before showing the dialog you can do something like this
This worked for me.