Android移除Fragment和View从BackStack

35

在此输入图像描述

我意识到这个问题之前已经被问过了,但之前的答案只帮我解决了一部分。情景如下:我们有一个仪表板片段(A),它会将用户引导到登录界面(B)。在成功登录后,他们会进入一个列表视图(C)。在返回按钮按下时,我想返回到A,因为用户不需要再次看到登录屏幕。另外,在成功登录后,我们将详细信息存储在共享首选项中,并在下次自动登录B,这一切都按计划进行。

我有以下FragmentHelper方法:

public static void goToNextFragement(Fragment fragment, int container, boolean addToBackStack, Fragment ctx)
    {
        // Create new fragment and transaction
        FragmentTransaction transaction = ctx.getSupportFragmentManager().beginTransaction();
        transaction.setCustomAnimations(R.anim.slide_in_left, R.anim.slide_out_right);
        // Replace whatever is in the fragment_container view with this fragment,
        // and add the transaction to the back stack
        transaction.replace(container, fragment);

        if(addToBackStack)
            transaction.addToBackStack(null);

        // Commit the transaction
        transaction.commit();
    }
在从B到C的事务中,我将addToBackStack布尔值设置为false,以便不调用transaction.addToBackStack(null);。这再次很好地起作用,但问题发生在之后。

当用户在C上按返回并返回A时,我仍然可以看到A视图下充气的C视图。

任何帮助都将不胜感激。我希望我的图表有助于保持简单。

6个回答

23

我用一行代码解决了这个问题。

getFragmentManager().popBackStack();
或者
getSupportFragmentManager().popBackStack()

当您添加片段并维护后退栈(而不是替换)时,这将起作用。


2
当您从2到3跳转之前,如果您在回退堆栈中弹出,则系统会尝试显示片段1。每次弹出片段N时,它都会尝试显示片段(N-1)。如果您强制转到片段3,则在片段1的onCreateView期间会发生NPE错误... - Yazon2006

6

f1 -> f2

Fragment2 f2 = new Fragment2();
this.getActivity().getSupportFragmentManager().beginTransaction().replace(R.id.main_content,f2).addToBackStack(null).commit();

这里没有什么特别的。然后在片段f2中,这段代码会带您到片段f3。

f2 -> f3

Fragment3 f3 = new Fragment3();
getActivity().getSupportFragmentManager().popBackStack();
getActivity().getSupportFragmentManager().beginTransaction().replace(R.id.main_content, f3).addToBackStack(null).commit();

通过阅读文档,我不确定这是否有效。说这个弹出事务方法是异步的,也许更好的方法是调用popBackStackImmediate()。但就我所知,在我的设备上它运行得非常顺畅。

所述的替代方法如下:

final FragmentActivity activity = getActivity();
activity.getSupportFragmentManager().popBackStackImmediate();
activity.getSupportFragmentManager().beginTransaction().replace(R.id.main_content, f3).addToBackStack(null).commit();

在继续进行f3之前,实际上会简要回顾f1,所以会有一些小问题。

这实际上是你需要做的全部内容,而这个答案也可以帮助你很多。


你的解决方案非常完美,对我的问题帮助很大,你节省了我的时间,Nepster。 - Adnan Abdollah Zaki

1
步骤1:当您在片段A中并且想要打开片段B时。
getFragmentManager().beginTransaction()
.replace(android.R.id.content, new FragmentB(), FragmentB.class.getName()
.addToBackStack(null)
.commit();

步骤2:当您在片段B中并且想要打开片段C时
getFragmentManager().beginTransaction()
.replace(android.R.id.content, new FragmentC(), FragmentC.class.getName()
.disallowAddToBackStack() // << this to make Fragment B, not included in the backstack
.commit();

第三步: 当您在Fragment C中,按下设备返回按钮或getFragmentManager().popBackStack();时,将打开Fragment A。
PS: 在Activity中使用getSupportFragmentManager()。如果您在Fragment中,请使用getFragmentManager()

1

处理这个问题的几种方法:

  1. 我在我的应用程序中有一个类似的流程,我解决它的方法是用一个从主活动触发的AlertDialog替换登录片段。 因此,在您的情况下,片段A出现在屏幕上,如果主活动认为需要显示登录对话框,则会显示AlertDialog。这对我有用。

  2. 当启用片段A时,它可以通过询问FragmentManager是否存在片段C来检查它。如果存在,则删除它。


AlertDialog是个不错的选择。感谢您分享您的经验。 - Graham Smith

0

嗨,我只是想分享我找到的优雅解决方案。

public static void performNoBackStackTransaction(FragmentManager fragmentManager, String tag, Fragment fragment) {
final int newBackStackLength = fragmentManager.getBackStackEntryCount() +1;

fragmentManager.beginTransaction()
    .replace(R.id.content, fragment, tag)
    .addToBackStack(tag)
    .commit();

fragmentManager.addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
  @Override
  public void onBackStackChanged() {
    int nowCount = fragmentManager.getBackStackEntryCount();
    if (newBackStackLength != nowCount) {
      // we don't really care if going back or forward. we already performed the logic here.
      fragmentManager.removeOnBackStackChangedListener(this);

      if ( newBackStackLength > nowCount ) { // user pressed back
        fragmentManager.popBackStackImmediate();
      }
    }
  }
});
}

带有解释逻辑的源代码


0
不告诉FM你希望将从B到C的过渡添加到backStack中意味着当你点击返回按钮时,FM没有记录添加C的操作,因此它不会将其移除。

好的,我认为这可能是情况,但是(冒着听起来不感激帮助的风险,我并不是这样)这只是对问题的分析,而不是解决方案。你有任何想法可以解决/修复这个问题吗? - Graham Smith
从我的角度来看,你可以手动删除该片段,但这可能不是最佳选择。除此之外,你需要自己做功课。 - Kelly Merrell

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接