DialogFrag#秀()从片段投掷" IllegalStateException异常:无法执行的onSaveInstanceState&QUOT后,这个动作; [英] DialogFrag#show() from a Fragment throwing "IllegalStateException: Can not perform this action after onSaveInstanceState"

本文介绍了DialogFrag#秀()从片段投掷" IllegalStateException异常:无法执行的onSaveInstanceState&QUOT后,这个动作;的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

只是要清楚,我看了十几个顶级的SO问题IllegalStateException异常:以后的onSaveInstanceState无法执行此操作,我读过关于这个问题的http://www.androiddesignpatterns.com/2013/08/fragment-transaction-commit-state-loss.html

Just to be clear, I have read the dozen top SO questions on "IllegalStateException: Can not perform this action after onSaveInstanceState" and I have read Alex Lockwood's blog post on the issue http://www.androiddesignpatterns.com/2013/08/fragment-transaction-commit-state-loss.html

所以我不会问这个盲目的。

So I'm not asking this blindly.

我有一个非常简单的用例情况下的涉及的AsyncTask或任何后台处理。

I have a very simple use case case that doesn't involve AsyncTask or any background processing.

我有一个包含一个按钮的片段。在onClickListener的按钮,我创建了一个DialogFragment,并显示它。

I have a Fragment that contains a button. On the onClickListener for the button, I create a DialogFragment and show it.

public final class OverviewFragment extends Fragment {
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        final View view = inflater.inflate(R.layout.overview_fragment, container, false);

        startNewGameButton = (Button) view.findViewById(R.id.buttonNewGame);
        startNewGameButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                final NewGameFragment dialogFrag = NewGameFragment.create(getApplication());
                dialogFrag.show(getFragmentManager(), NewGameFragment.FRAGMENT_TAG);
            }
        });
}

[NewGameFragment]

[NewGameFragment]

public final class NewGameFragment extends DialogFragment {

    public static final String FRAGMENT_TAG = "NewGameFragment";

    private static final String MESSAGE = "message";

    public static NewGameFragment create(Context context) {
        final AppsPreferences prefs = new AppPreferences(context);
        final int startOption = prefs.getGameStartOption();

        final Bundle bundle = new Bundle();
        bundle.putString(MESSAGE, getMessage(context, startOption));

        final NewGameFragment fragment = new NewGameFragment();
        fragment.setArguments(bundle);
        return fragment;
    }

    @Override
    public final Dialog onCreateDialog(Bundle savedInstanceState) {
        final String message = getArguments().getString(MESSAGE);

        final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity())
            .setTitle(R.string.progress_startGame_title)
            .setMessage(message);

        builder.setPositiveButton(R.string.progress_startGame_raceButton, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                new RaceAction().execute();
            }
        });
        builder.setNegativeButton(R.string.progress_startGame_eventButton, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                new EventAction().execute();
            }
        });

        final Dialog dialog = builder.create();
        dialog.setCanceledOnTouchOutside(false); // Whether clicking outside the dialog closes the dialog.
        return dialog;
    }
  }

[堆栈跟踪]

[Stacktrace]

java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
at android.support.v4.app.FragmentManagerImpl.void checkStateLoss()(SourceFile:1365)
at android.support.v4.app.FragmentManagerImpl.void enqueueAction(java.lang.Runnable,boolean)(SourceFile:1383)
at android.support.v4.app.BackStackRecord.int commitInternal(boolean)(SourceFile:636)
at android.support.v4.app.BackStackRecord.int commit()(SourceFile:615)
at android.support.v4.app.DialogFragment.void show(android.support.v4.app.FragmentManager,java.lang.String)(SourceFile:138)
at au.com.xandar.thegame.overview.OverviewFragment$1.void onClick(android.view.View)(SourceFile:160)
at android.view.View.performClick(View.java:4162)
at android.view.View$PerformClick.run(View.java:17082)
at android.os.Handler.handleCallback(Handler.java:615)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4867)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1007)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:774)
at dalvik.system.NativeStart.main(Native Method)

NB的片段和DialogFragment都来自支持-V4:21.0.0

NB the Fragment and DialogFragment both come from support-v4:21.0.0

我在多种设备上运行4.4见状。但至少一个实例上发生一个的Nexus 7运行5.0

I am seeing this on a range of devices running 4.4. But at least one instance has occurred on a Nexus 7 running 5.0.

我一直没能复制这个自己。甚至没有通过引入人为的延迟到的onClick并试图旋转,回,家里的应用程序。

I have not been able to replicate this myself. Not even by introducing an artificial delay into the onClick and attempting to rotate, back, home the app.

所以,因为 FragmentTransaction (对于 DialogFrag#秀())正在创建并承诺在UI线程直接从的onClick(),怎么能片段已经着手过去的onSaveInstanceState()

So since the FragmentTransaction (for DialogFrag#show()) is being created and committed on the UI Thread directly from onClick(), how can the Fragment already have proceeded past onSaveInstanceState()?

这是否意味着我需要检查每用户输入的开始的活动生命周期的状态? - 很糟糕(的生命周期,就是要处理,对我我不应该接收用户输入,如果活动已经是过去的onPause()

Does it mean that I need to check the state of the Activity Lifecycle at the start of every user input? - very bad (the Lifecycle is meant to be handling that for me. I shouldn't be receiving user input if the Activity is already past onPause())

这是否意味着我需要执行用户输入的过程中,检查活动的生命周期之前,每个语句的状态呢? - 破坏!!

Does it mean I need to check the state of the Activity Lifecycle prior to every statement during execution of user input? - broken bad !!

我能做些什么来阻止发生这种情况?

What can I do to stop this occurring?

更多信息:

在野外几天跑,我可以明确地说, getChildFragmentManager()是解决不了问题。

After running in the wild for several days I can categorically say that getChildFragmentManager() is not the solution.

发生故障时以下的Andr​​oid版本:

Failure occurs for the following Android versions:

  • 在4.4.2 90%
  • 在4.4.4 5%
  • 5.0 5%

推荐答案

确定,据我可以告诉这是一个的错误在AOSP,我也看到了从单纯的Andr​​oid栈的这一个实例(也就是没有我的code在所有)。

OK, as far as I can tell this is a bug in the AOSP as I have also seen an instance of this from pure Android stack (ie nothing of my code at all).

因此​​,它看起来像有一个线程问题在活动/片段的生命周期中,UI线程可以得到优先考虑到一个按钮点击 在响应活动/片段已经保存它的状态。

So it looks like there is a threading issue in the Activity/Fragment lifecycle in which a UI thread can get priority to respond to a button click AFTER the Activity/Fragment has already saved it's state.

我的工作围绕它已经100%成功的,到目前为止是赶上IllegalStateException异常并安排对话框显示下一次使用PauseHandler的 http://stackoverflow.com/a/25322330/493682

My work around which has been 100% successful so far is to catch the IllegalStateException and schedule the dialog show for the next time the Activity/Fragment becomes active using a PauseHandler http://stackoverflow.com/a/25322330/493682

这篇关于DialogFrag#秀()从片段投掷" IllegalStateException异常:无法执行的onSaveInstanceState&QUOT后,这个动作;的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆