Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/205.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/matlab/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android FragmentTransaction:replace和addToBackStack不一起工作?_Android_Android Fragments_Fragmenttransaction - Fatal编程技术网

Android FragmentTransaction:replace和addToBackStack不一起工作?

Android FragmentTransaction:replace和addToBackStack不一起工作?,android,android-fragments,fragmenttransaction,Android,Android Fragments,Fragmenttransaction,我对安卓系统的开发相当陌生,现在遇到了奇怪的行为 我有一个空的FrameLayout作为片段的容器 若用户第一次按下按钮,生成新片段并放入容器中 若用户稍后按下按钮,并且容器中存在现有片段,则将现有片段替换为新生成的片段 如果用户按下后退按钮,弹出容器内的碎片 这是我的密码 public void showFragment(View v) { FragmentA f = new FragmentA(); FragmentManager fm = getSupportFrag

我对安卓系统的开发相当陌生,现在遇到了奇怪的行为

  • 我有一个空的FrameLayout作为片段的容器
  • 若用户第一次按下按钮,生成新片段并放入容器中
  • 若用户稍后按下按钮,并且容器中存在现有片段,则将现有片段替换为新生成的片段
  • 如果用户按下后退按钮,弹出容器内的碎片
这是我的密码

public void showFragment(View v) {
    FragmentA f = new FragmentA();

    FragmentManager fm = getSupportFragmentManager();
    String tag = f.getFragmentTag(); // instance method of a to get a tag

    FragmentTransaction ft = fm.beginTransaction();
    ft.setCustomAnimations(R.anim.slide_in_top, 0, 0, R.anim.slide_out_top);            
    ft.replace(R.id.container, f, tag);
    ft.addToBackStack(tag);
    ft.commit();
}

@Override
public void onBackPressed() {
    FragmentManager fm = getSupportFragmentManager();
    if (fm.getBackStackEntryCount() > 0) {
        fm.popBackStack();
    } else {
        super.onBackPressed();
    }
}
当用户第一次按下按钮时,它的行为和我预期的一样,将新片段添加到容器中。但是,当用户第二次按下按钮时,容器仍然包含一个片段,而不是替换,而是在现有片段的基础上添加新片段So,容器内有2个碎片,2次后按可移除所有碎片。

我发现,如果我删除该行

ft.addToBackStack();
重新编写onBackPress()方法,如下所示,它再次像我预期的那样工作(一次在容器中放入1个片段)

基本上,手动删除片段,而不是popFromBackStack方法

private FragmentA currentFragment = null; // to hold the reference to exising fragment, if any.

@Override
public void onBackPressed() {
    if (currentFragment != null) {
        FragmentManager fm = getSupportFragmentManager();
        FragmentTransaction ft = fm.beginTransaction();
        ft.setCustomAnimations(0, R.anim.slide_out_top);
        ft.remove(currentFragment);
        ft.commit();

        currentFragment = null;
    } else {
        super.onBackPressed();
    }
}
所以,我的问题是

  • replace和addToBackStack不一起工作
  • 或者,我做错什么了吗

感谢所有评论和建议。

addToBackstack
创建片段状态的快照。这意味着,当您按下“后退”按钮时,实际上正在恢复到上次调用
addToBackstack
的状态


在本例中,您添加了一个片段。后退按钮将删除此添加的片段。调用replace并再次添加到backstack时,backstack上现在有两个状态(1.添加第一个片段时,2.未添加片段时)。如果单击“上一步”按钮删除当前片段,则不使用addToBackstack。仅当您希望在视图中保留片段的状态时才使用addToBackstack。

对于仍在寻找解决方案的用户

在主
Activity
类(它承载片段)中,只需覆盖
onBackPressed()

片段中没有
onBackPressed()
方法,此方法仅用于
活动
。因此,当我们按下后退键时,将显示
活动的默认行为,即

您将转到以前的活动(如果有)或应用程序 将退出

现在,我们需要重写此方法,告诉
活动
当我们按下后退键时,如果在后堆栈中有任何片段,请将其弹出(这是当
addToBackStack()
进入图片时)。否则,遵循默认行为


在此处查找更多详细信息

嗨,Spidy,谢谢您的评论。我仍然很困惑,但我可以说,在我的情况下,我不应该使用addToBackStack吗?是的,听起来你不需要addToBackStack来使用case@Spidy在安卓开发者网站上,他们说你应该使用addToBackStack在片段之间导航时提供正确的反向导航。你不使用它们的理由是什么?和2:“在你的例子中,你添加了一个片段。后退按钮将删除这个添加的片段。当你调用replace,并再次添加到backstack时,你现在在backstack上有两个状态”。他在代码中的什么地方添加了一个片段?我只看到replace(),我认为这就是原因:“如果在执行删除片段的事务时不调用addToBackStack(),那么在提交事务时该片段将被销毁,用户无法导航回它。然而,如果调用addToBackStack())删除片段时,该片段将停止,如果用户返回,该片段将继续。“使用addToBackStack()时,先前的片段将停止并保留。见:
@Override
public void onBackPressed() {
    if (getFragmentManager().getBackStackEntryCount() > 0 ){
        getFragmentManager().popBackStack();
    } else {
        super.onBackPressed();
    }
}