Android DialogFrag“从碎片投掷中显示”;IllegalStateException:在onSaveInstanceState”之后无法执行此操作;
为了明确起见,我已经阅读了关于“非法州例外:在onSaveInstanceState之后不能执行此操作”的12个最重要的SO问题,并且我已经阅读了Alex Lockwood关于此问题的博客文章 所以我不是盲目地问这个问题 我有一个非常简单的用例,不涉及异步任务或任何后台处理 我有一个包含按钮的片段。在按钮的onClickListener上,我创建了一个DialogFragment并显示它Android DialogFrag“从碎片投掷中显示”;IllegalStateException:在onSaveInstanceState”之后无法执行此操作;,android,android-fragments,android-dialogfragment,android-lifecycle,android-nested-fragment,Android,Android Fragments,Android Dialogfragment,Android Lifecycle,Android Nested Fragment,为了明确起见,我已经阅读了关于“非法州例外:在onSaveInstanceState之后不能执行此操作”的12个最重要的SO问题,并且我已经阅读了Alex Lockwood关于此问题的博客文章 所以我不是盲目地问这个问题 我有一个非常简单的用例,不涉及异步任务或任何后台处理 我有一个包含按钮的片段。在按钮的onClickListener上,我创建了一个DialogFragment并显示它 public final class OverviewFragment extends Fragment {
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);
}
});
}
[新游戏片段]
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)
注意:片段和对话框片段都来自support-v4:21.0.0
我在一系列运行4.4的设备上看到了这一点。但运行5.0的Nexus7上至少出现了一个实例
我自己也无法复制这一点。即使在onClick中引入人工延迟并尝试旋转、返回应用程序的主页,也不行
既然FragmentTransaction
(对于DialogFrag#show()
)是直接从onClick()
在UI线程上创建和提交的,那么片段如何已经通过onSaveInstanceState()
这是否意味着我需要在每次用户输入开始时检查活动生命周期的状态非常糟糕(生命周期本来是要为我处理的。如果活动已经过了onPause()
,我就不应该收到用户输入)
这是否意味着在执行用户输入期间,我需要在每条语句之前检查活动生命周期的状态坏透了
我能做些什么来阻止这种情况发生
更多信息:
在野外运行了几天之后,我可以肯定地说getChildFragmentManager()
不是解决方案
以下Android版本出现故障:
- 4.4.2 90%
- 4.4.4.5%
- 5.05%
好的,据我所知,这是AOSP中的一个实例,因为我还看到了纯Android堆栈中的一个实例(即我的代码中没有任何内容)
因此,在“活动/片段”生命周期中似乎存在线程问题,在“活动/片段”保存其状态后,UI线程可以优先响应按钮单击
到目前为止,我的工作已经取得了100%的成功,我的工作是捕获IllegalStateException,并使用PauseHandlerpost NewGameFragment类将其移动到创建的活动上的BlazeTama move what?显示对话框?这违背了在用户单击按钮时显示它的目的。@William抱歉,我的意思是尝试将startNewGameButton.setOnClickListener
移动到onActivityCreated
,onClick
仍将工作fine@SweetWisherツ DialogFrag代码已添加。您好,遇到了相同的问题。你有没有在AOSP问题跟踪器中登录过它?谢谢,我之前检查过很多类似的AOSP错误。令人惊讶的是,它们都被标记为过时。