在我的onActivityResult中,我的一个片段有以下代码:
onActivityResult(int requestCode, int resultCode, Intent data){
//other code
ProgressFragment progFragment = new ProgressFragment();
progFragment.show(getActivity().getSupportFragmentManager(), PROG_DIALOG_TAG);
// other code
}
但是,我得到了以下错误:
Caused by: java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
有人知道这是怎么回事吗,或者我怎么解决这个问题?我需要注意的是,我使用的是Android支持包。
发布于 2013-04-04 11:38:35
如果你使用Android支持库,onResume方法不是正确的地方,在那里玩碎片。应该在onResumeFragments方法中完成,参见onResume方法说明:http://developer.android.com/reference/android/support/v4/app/FragmentActivity.html#onResume%28%29
因此,从我的角度来看,正确的代码应该是:
private boolean mShowDialog = false;
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data){
super.onActivityResult(requestCode, resultCode, data);
// remember that dialog should be shown
mShowDialog = true;
}
@Override
protected void onResumeFragments() {
super.onResumeFragments();
// play with fragments here
if (mShowDialog) {
mShowDialog = false;
// Show only if is necessary, otherwise FragmentManager will take care
if (getSupportFragmentManager().findFragmentByTag(PROG_DIALOG_TAG) == null) {
new ProgressFragment().show(getSupportFragmentManager(), PROG_DIALOG_TAG);
}
}
}
发布于 2012-04-12 06:35:04
编辑:不是bug,而是fragments框架中的一个缺陷。这个问题的更好答案是上面@Arcao提供的答案。
-原始帖子
实际上,它是一个带有支持包的known bug (编辑:实际上不是一个bug。参见@alex-lockwood的评论)。在错误报告的注释中发布的解决方法是修改DialogFragment的源代码,如下所示:
public int show(FragmentTransaction transaction, String tag) {
return show(transaction, tag, false);
}
public int show(FragmentTransaction transaction, String tag, boolean allowStateLoss) {
transaction.add(this, tag);
mRemoved = false;
mBackStackId = allowStateLoss ? transaction.commitAllowingStateLoss() : transaction.commit();
return mBackStackId;
}
请注意,这是一个巨大的黑客攻击。我实际做的方法是制作我自己的对话片段,我可以从原始片段中注册。当另一个对话框片段做了一些事情(比如被解除)时,它会告诉任何监听器它正在消失。我是这样做的:
public static class PlayerPasswordFragment extends DialogFragment{
Player toJoin;
EditText passwordEdit;
Button okButton;
PlayerListFragment playerListFragment = null;
public void onCreate(Bundle icicle){
super.onCreate(icicle);
toJoin = Player.unbundle(getArguments());
Log.d(TAG, "Player id in PasswordFragment: " + toJoin.getId());
}
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle icicle){
View v = inflater.inflate(R.layout.player_password, container, false);
passwordEdit = (EditText)v.findViewById(R.id.player_password_edit);
okButton = (Button)v.findViewById(R.id.ok_button);
okButton.setOnClickListener(new View.OnClickListener(){
public void onClick(View v){
passwordEntered();
}
});
getDialog().setTitle(R.string.password_required);
return v;
}
public void passwordEntered(){
//TODO handle if they didn't type anything in
playerListFragment.joinPlayer(toJoin, passwordEdit.getText().toString());
dismiss();
}
public void registerPasswordEnteredListener(PlayerListFragment playerListFragment){
this.playerListFragment = playerListFragment;
}
public void unregisterPasswordEnteredListener(){
this.playerListFragment = null;
}
}
因此,现在我有一种方法可以在发生事情时通知PlayerListFragment。请注意,适当地调用unregisterPasswordEnteredListener非常重要(在上面的例子中,当PlayerListFragment“消失”时),否则当注册的侦听器不再存在时,此对话框片段可能会尝试调用该侦听器上的函数。
发布于 2012-04-12 05:54:36
我相信这是一个Android的bug。基本上,安卓在活动/片段生命周期中的错误位置(在onStart()之前)调用onActivityResult。
该漏洞已在https://issuetracker.google.com/issues/36929762上报告
我基本上通过将意图存储为稍后在onResume()中处理的参数来解决它。
编辑对于这个问题,现在有更好的解决方案,这在2012年是不存在的。请参阅其他答案。
https://stackoverflow.com/questions/10114324
复制相似问题