Kur*_*aum 79 android android-fragments android-dialogfragment
我的onActivityResult中有以下代码用于我的片段:
onActivityResult(int requestCode, int resultCode, Intent data){
//other code
ProgressFragment progFragment = new ProgressFragment();
progFragment.show(getActivity().getSupportFragmentManager(), PROG_DIALOG_TAG);
// other code
}
Run Code Online (Sandbox Code Playgroud)
但是,我收到以下错误:
Caused by: java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
Run Code Online (Sandbox Code Playgroud)
有谁知道发生了什么,或者我如何解决这个问题?我应该注意到我正在使用Android支持包.
Arc*_*cao 73
如果你使用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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
Kur*_*aum 27
编辑:不是一个错误,但更多的是片段框架的缺陷.这个问题的更好答案是上面提到的@Arcao.
----原帖----
实际上这是支持包的一个已知错误(编辑:实际上不是一个错误.请参阅@ 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;
}
Run Code Online (Sandbox Code Playgroud)
请注意,这是一个巨大的黑客.我实际做的方式就是制作我自己的对话框片段,我可以从原始片段注册.当其他对话片段做了事情(比如被解雇)时,它告诉任何听众它已经消失了.我是这样做的:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
所以现在我有办法在事情发生时通知PlayerListFragment.请注意,正确调用unregisterPasswordEnteredListener非常重要(在上述情况下,当PlayerListFragment"消失"时),否则此对话框片段可能会尝试在该侦听器不再存在时调用已注册侦听器上的函数.
twi*_*wig 21
@Natix留下的评论是一个快速的单行,有些人可能已经删除.
解决这个问题最简单的方法是在运行自己的代码之前调用super.onActivityResult().无论您是否使用支持库,这都有效,并在您的活动中保持行为一致性.
有:
我读到的越多,我看到的更疯狂的黑客.
如果你仍然遇到问题,那么Alex Lockwood的那个就是要检查的那个.
hrn*_*rnt 14
Android __CODE__之前的电话__CODE__.
我通过基本上将Intent存储为我稍后处理的参数来解决它__CODE__.
小智 11
编辑:还有另一种选择,可能是最好的(或者,至少支持库期望的......)
如果您将DialogFragments与Android支持库一起使用,则应该使用FragmentActivity的子类.请尝试以下方法:
onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, intent);
//other code
ProgressFragment progFragment = new ProgressFragment();
progFragment.show(getActivity().getSupportFragmentManager(), PROG_DIALOG_TAG);
// other code
}
Run Code Online (Sandbox Code Playgroud)
我看了一下FragmentActivity 的源代码,看起来它正在调用一个内部片段管理器,以便在不丢失状态的情况下恢复片段.
我找到了一个未列在此处的解决方案.我创建一个Handler,并在Handler中启动对话框片段.所以,编辑你的代码:
onActivityResult(int requestCode, int resultCode, Intent data) {
//other code
final FragmentManager manager = getActivity().getSupportFragmentManager();
Handler handler = new Handler();
handler.post(new Runnable() {
public void run() {
ProgressFragment progFragment = new ProgressFragment();
progFragment.show(manager, PROG_DIALOG_TAG);
}
});
// other code
}
Run Code Online (Sandbox Code Playgroud)
这对我来说似乎更干净,也更不那么惹人讨厌.
有两个DialogFragment show()方法 - show(FragmentManager manager, String tag)和show(FragmentTransaction transaction, String tag).
如果你想使用该方法的FragmentManager版本(如在原始问题中),一个简单的解决方案是覆盖此方法并使用commitAllowingStateLoss:
public class MyDialogFragment extends DialogFragment {
@Override
public void show(FragmentManager manager, String tag) {
FragmentTransaction ft = manager.beginTransaction();
ft.add(this, tag);
ft.commitAllowingStateLoss();
}
}
Run Code Online (Sandbox Code Playgroud)
覆盖show(FragmentTransaction, String)这种方式并不容易,因为它还应该修改原始DialogFragment代码中的一些内部变量,所以我不推荐它 - 如果你想使用那个方法,那么尝试接受的答案中的建议(或者来自的注释)杰弗里布拉特曼).
使用commitAllowingStateLoss存在一些风险 - 文档声明"Like commit()"但允许在保存活动状态后执行提交.这很危险,因为如果活动需要稍后从状态恢复,则提交可能会丢失,所以这只应该用于UI状态可以在用户上意外更改的情况."
| 归档时间: |
|
| 查看次数: |
37587 次 |
| 最近记录: |