简体   繁体   English

java.lang.IllegalStateException:使用DialogFragment在onSaveInstanceState之后无法执行此操作

[英]java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState with DialogFragment

I am facing issue with DialogFragment / getSupportFragmentManager / Android version 4.x 我遇到DialogFragment / getSupportFragmentManager / Android 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). 代码在较旧的版本(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");
    }
}

Here is the answer in another thread: 这是另一个线程的答案:

Actions in onActivityResult and "Error Can not perform this action after onSaveInstanceState" onActivityResult中的操作和“错误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();  

I got the same issue and I changed the code as bellow 我遇到了同样的问题,我将代码更改为以下

newFragment.show(transactionFragment, "dialog");

to: 至:

transactionFragment.add(android.R.id.content, newFragment).addToBackStack(null).commitAllowingStateLoss();

the completed code works well for me as bellow, hope that help 完整的代码对我来说非常好,希望对您有所帮助

FragmentTransaction transactionFragment = getActivity().getSupportFragmentManager().beginTransaction();
    DialogPageListFragment newFragment = new DialogPageListFragment();
    transactionFragment.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
    newFragment.setArguments(extras);
    transactionFragment.add(android.R.id.content, newFragment).addToBackStack(null).commitAllowingStateLoss();

Probably, the handler that is responding to the HandleMessage is associated to a destroyed activity. 可能是,响应HandleMessage的处理程序与已破坏的活动相关联。

ie: If you rotate the screen, the old destroyed activity will handle the message, then you will call showDialog, and the exception will be thrown: 例如:如果旋转屏幕,旧的被破坏的活动将处理该消息,然后您将调用showDialog,并且将引发异常:

You are creating a dialog after the old destroyed activity has called his onSaveInstanceState. 在旧的已销毁活动调用其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. 如果您不旋转,请在onSaveInstance上放置一个标记(例如“ saving”),然后在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. 在您的handleMessage方法中,如果打开了“保存”标志,则不显示对话框,只需打开另一个标志,表明必须在onResume上创建对话框。 Then on onResume method, check if in middle of that process, you should create the dialog, if yes, show it on onResume method. 然后在onResume方法上,检查是否在该过程的中间,应该创建对话框,如果是,则在onResume方法上显示该对话框。

fragmentView.post(() -> {
    FragmentTransaction ft = getActivity().getSupportFragmentManager().beginTransaction();
    YourDialog yourDialog = YourDialog.newInstance();
    yourDialog.show(ft, "text_data");
});

The goal of post() method in this case is to wait while onResume() of Activity or Fragment will finished. 在这种情况下,post()方法的目标是等待Activity或Fragment的onResume()完成。 It works if you want to show DialogFragment from Fragment., fe when you want to show your dialog after a system dialog dismissed. 如果您想在关闭系统对话框后显示对话框,则可以从Fragment.fe中显示DialogFragment。

I was facing the same issue when post delaying Runnables handler.postDelayed(Runnable runnable, long delayed). 发布延迟Runnables handler.postDelayed(Runnable runnable,长时间延迟)时,我面临着同样的问题。

I have solved the problem this way: 我已经通过这种方式解决了这个问题:

  1. In onSaveInstanceState I cancel the delayed tasks 在onSaveInstanceState中,我取消了延迟的任务
  2. In onRestoreInstanceState I recreate the task if there have been delayed tasks when activity was destroyed 在onRestoreInstanceState中,如果活动被破坏时有延迟的任务,我将重新创建任务

too late answer but may be the correct answer. 答案为时已晚,但可能是正确答案。 I made a parent class and and dialog fragment extends from it 我做了一个父类,对话框片段从中扩展了

 public class BaseDialogFragment extends DialogFragment {

@Override
public void show(FragmentManager manager, String tag) {
    try {
        FragmentTransaction ft = manager.beginTransaction();
        ft.add(this, tag).addToBackStack(null);
        ft.commitAllowingStateLoss();
    } catch (IllegalStateException e) {
        Log.d("ABSDIALOGFRAG", "Exception", e);
    }
}

boolean mIsStateAlreadySaved = false;
boolean mPendingShowDialog = false;

@Override
public void onResume() {
    onResumeFragments();
    super.onResume();
}

public void onResumeFragments(){
    mIsStateAlreadySaved = false;
    if(mPendingShowDialog){
        mPendingShowDialog = false;
        showSnoozeDialog();
    }
}

@Override
public void onPause() {
    super.onPause();
    mIsStateAlreadySaved = true;
}

private void showSnoozeDialog() {
    if(mIsStateAlreadySaved){
        mPendingShowDialog = true;
    }else{
        FragmentManager fm = getFragmentManager();
        BaseDialogFragment snoozeDialog = new BaseDialogFragment();
        snoozeDialog.show(fm, "BaseDialogFragment");
    }
}

} }

onPostResume()使用后恢复的方法做你的工作。我认为你调用onRestart或表演的onResume方法对话框,所以要避免它,并使用onPostResume()来显示你的对话框。

You could check if the current activity isActive() and only in that case start the fragment transaction of DialogFragment. 您可以检查当前活动是否为isActive(),仅在这种情况下才启动DialogFragment的片段事务。 I had a similar problem and this check solved my case. 我遇到了类似的问题,这项检查解决了我的问题。

It works: 有用:

CheckinSuccessDialog dialog = new CheckinSuccessDialog();
//dialog.show(getSupportFragmentManager(), null);
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.add(dialog, null);
ft.commitAllowingStateLoss();

But but still bad, because got error “Activity has been destroyed” 但仍然很糟糕,因为出现错误“活动已被破坏”

 ava.lang.IllegalStateException: Activity has been destroyed fragmentTransaction.commitAllowingStateLoss();

So my solution is add check if (!isFinishing()&&!isDestroyed()) 所以我的解决方案是添加检查if (!isFinishing()&&!isDestroyed())

CheckinSuccessDialog fragment = CheckinSuccessDialog.newInstance();

  if (fragment instanceof DialogFragment) {
                DialogFragment dialog = (DialogFragment) fragment;
                if (!dialog.isAdded()) {
                    fragmentTransaction.add(dialog, 
                          CheckinSuccessDialog.class.getName());
                    if (!isFinishing()&&!isDestroyed()) {
                        fragmentTransaction.commitAllowingStateLoss();
                    }
                }

on dismiss: 解雇时:

  FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
            Fragment fragment = getSupportFragmentManager().findFragmentByTag(CheckinSuccessDialog.class.getName());
            if (fragment != null && fragment instanceof DialogFragment) {
                DialogFragment dialog = (DialogFragment) fragment;
                dialog.dismiss();
                if (!isFinishing()&&!isDestroyed()) {
                    fragmentTransaction.commitAllowingStateLoss();
                }
            }

In the Activity , before showing the dialog you can do something like this 在“ 活动”中 ,在显示对话框之前,您可以执行以下操作

getSupportFragmentManager().executePendingTransactions();

This worked for me. 这对我有用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 java.lang.IllegalStateException-在onSaveInstanceState之后无法执行此操作 - java.lang.IllegalStateException - Can not perform this action after onSaveInstanceState java.lang.IllegalStateException(在onSaveInstanceState之后无法执行此操作) - java.lang.IllegalStateException(Can not perform this action after onSaveInstanceState) 由 java.lang.IllegalStateException 引起 onSaveInstanceState 后无法执行此操作 - Caused by java.lang.IllegalStateException Can not perform this action after onSaveInstanceState java.lang.IllegalStateException:onSaveInstanceState之后无法执行此操作 - java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState java.lang.IllegalStateException:onSaveInstanceState,FragmentTabHost之后无法执行此操作 - java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState,FragmentTabHost Android java.lang.IllegalStateException:onSaveInstanceState之后无法执行此操作 - Android java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState java.lang.IllegalStateException: 在 onSaveInstanceState 之后无法执行此操作 - java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState 异常java.lang.IllegalStateException:onSaveInstanceState之后无法执行此操作 - Exception java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState onWaveInstanceState之后的TabWidget onClick(java.lang.IllegalStateException:在onSaveInstanceState之后无法执行此操作) - TabWidget onClick after onSaveInstanceState (java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState) fragmentTransaction.commit()上的“ java.lang.IllegalStateException:在onSaveInstanceState之后无法执行此操作” - “java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState” on fragmentTransaction.commit()
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM