DialogFrag#秀()从片段投掷" IllegalStateException异常:无法执行的onSaveInstanceState&QUOT后,这个动作; [英] DialogFrag#show() from a Fragment throwing "IllegalStateException: Can not perform this action after onSaveInstanceState"
问题描述
只是要清楚,我看了十几个顶级的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.
发生故障时以下的Android版本:
Failure occurs for the following Android versions:
- 在4.4.2 90%
- 在4.4.4 5%
- 5.0 5%
推荐答案
确定,据我可以告诉这是一个的错误在AOSP,我也看到了从单纯的Android栈的这一个实例(也就是没有我的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屋!