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

问题描述:

我对Android开发相当陌生,现在运行起来怪异的行为。FragmentTransaction:replace和addToBackStack不能一起工作?

  • 我有一个空的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(); 
    } 
} 

当用户按下按钮,第一次,它表现得像我所料,添加新的片段容器。但是,第二次用户按下按钮时,容器仍然包含一个片段,而不是替换,它会在现有的顶部添加一个新的。 因此,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(); 
    } 
} 

所以片段,我questio n分别是

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

感谢所有的意见和建议。

+0

我想这就是原因: “如果你不叫addToBackStack()当您进行交易,消除片段,则该片段是当事务提交销毁并且用户不能导航回去,而如果在删除片段时确实调用了addToBackStack(),则该片段将停止,并且如果用户返回,将会恢复。 当您使用addToBackStack()时,以前的片段将停止并保留。 请参阅:https://developer.android.com/guide/components/fragments.html#Transactions –

addToBackstack创建碎片状态的快照。这意味着当你按下后退按钮时,你实际上会回到addToBackstack被调用的最后一个状态。

在你的情况下,你添加一个片段。后退按钮将删除此添加的片段。当你调用replace时,再次添加到backstack中时,你现在在后台有两个状态(1.当你添加了第一个片段时,2.当你没有添加片段时)。如果你后退按钮删除当前片段,则不要使用addToBackstack。只有在想要保留视图中片段的状态时才使用addToBackstack。

+0

嗨Spidy,感谢您的评论。我仍然很困惑,但我可以说,在我的情况下,我不应该使用addToBackStack? –

+1

是的,它听起来像你不需要addToBackstack你的用例 – Spidy

+3

@Spidy在Android开发人员网站https://developer.android.com/training/implementing-navigation/temporal.html#back-fragments他们说,您应该使用addToBackStack在片段之间导航时提供正确的后退导航。你有什么理由不使用它们? 和2:“在你的情况下,你添加一个Fragment,后退按钮将删除这个添加的片段,当你调用replace时,再次添加到backstack,你现在有两个状态在backstack上。在他的代码中他添加了一个片段?我只看到replace() – Rule

对于那些仍在寻找解决方案的人。

在主Activity类(它是主办片段)只是覆盖onBackPressed()

@Override 
public void onBackPressed() { 
    if (getFragmentManager().getBackStackEntryCount() > 0){ 
     getFragmentManager().popBackStack(); 
    } else { 
     super.onBackPressed(); 
    } 
} 

中有片段没有onBackPressed()方法,而这种方法只是为了activity。所以,当我们按下返回键,中activity默认行为所示,这是

你要么去之前的活动(如果有的话)或应用 将退出。

现在我们需要重写这个方法告诉activity,当我们按下返回键,如果在后面堆栈中的任何片段,弹出出来(这是当addToBackStack()进入图片)。否则,请遵循默认行为。

找到更多的细节在这里here