编辑:不是错误,而是片段框架中的更多缺陷。这个问题的更好答案是上面@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;
}
请注意,这是一个巨大的黑客。我实际上这样做的方式只是制作我自己的对话片段,我可以从原始片段中注册。当另一个对话片段做一些事情(比如被解雇)时,它告诉任何听众它正在消失。我是这样做的:
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 “消失”时),否则当该侦听器不再存在时,此对话框片段可能会尝试调用已注册侦听器上的函数。