addToBackStack后的popBackStack()不起作用。

31

我的项目包含两个片段:

  • 片段A:应用程序启动时默认加载的片段
  • 片段B:当点击按钮时替换fragmentA

这是我的主视图的XML:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <fragment
        android:id="@+id/main_fragment_container"
        android:name="fragmentA"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    </fragment>

</LinearLayout>

当我希望用FragmentB替换FragmentA时,我使用以下代码:

FragmentTransaction fragmentTransaction = getSupportFragmentManager()
            .beginTransaction();
fragmentTransaction.addToBackStack(null);
fragmentTransaction.replace(R.id.main_fragment_container, new FragmentB());
fragmentTransaction.commit();

这段代码运行良好。我的FragmentA被新的FragmentB替换了。但是当点击返回按钮时,我希望使用popBackStackImmediate()FragmentB替换为FragmentA

这是我使用的代码:

if (getSupportFragmentManager().getBackStackEntryCount() > 0){
    boolean done = getFragmentManager().popBackStackImmediate();
    fragmentTransaction.commit();
}

popBackStackImmediate 函数总是返回 false,导致 FragmentB 仍在前台显示。

为什么当我调用 popBackStackImmediate 后,FragmentA 没有替换掉 FragmentB 呢?有没有人有解决问题的思路?

谢谢提前。


避免使用后退堆栈!它并不能真正提高整体效率!每次想要导航时,请使用普通的replace(),甚至更好的是删除/添加!请查看我的帖子https://dev59.com/qG025IYBdhLWcg3wyJCV#26093368。 - stack_ved
6个回答

48

使用 getSupportedFragmentManager() 方法将 FragmentA 替换为 FragmentB。但是你在 getFragmentManager() 上调用了 popBackStack()

如果你将 Fragments 添加到 android.support.v4.app.FragmentManager 中, 你也必须在同一 FragmentManager 上调用 popBackStack()

以下代码应该解决问题:

if (getSupportFragmentManager().getBackStackEntryCount() > 0){
    boolean done = getSupportFragmentManager().popBackStackImmediate();
}

在我的情况下,我在活动中使用supportedFragmentManager,在B中使用childFragmentManager打开C,当我在C中按下返回按钮时,它会将我发送到A而不是B。 - Beto Caldas

7
你应该调用 <\p>
fragmentTransaction.addToBackStack(null);

在执行所有操作(例如add(),remove()和replace())之后,且在commit()之前。只有这样,此事务才会被添加到后退堆栈中。只有这样,您才能使用 返回 按钮返回到先前的片段状态。详情请查看这里


7
问题在于您混合使用了Fragment和支持库中的方法。
如果您正在使用支持库,请确保:
- 您的Activity继承自android.support.v4.app.FragmentActivity - 您的Fragment继承自android.support.v4.app.Fragment - 使用getSupportFragmentManager()获取android.support.v4.app.FragmentManager 您在Activity中的代码应该是:
if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
   getSupportFragmentManager().popBackStackImmediate();
}

请注意,如果您想从Fragment代码获取FragmentManager,则必须使用getFragmentManager方法,如文档中所述(如果您没有太多经验,这可能是某些混淆的原因)。
如果您不使用支持库:
  • 您的Activity继承自android.app.Activity
  • 您的Fragment继承自android.app.Fragment
  • 使用getFragmentManager()来获取android.app.FragmentManager
您的代码将会是:
if (getFragmentManager().getBackStackEntryCount() > 0) {
   getFragmentManager().popBackStackImmediate();
}

fragmentTransaction.commit(); 在这两种情况下都是不必要的,因此请将其删除。

另外,请在其他操作之后但在commit之前调用fragmentTransaction.addToBackStack(null);


1
我建议使用带有标签的片段替换来产生相同的结果。
将 fragment B 添加到带有标签的活动中。
fragmentTransaction.replace(R.id.main_fragment_container, new FragmentB(),"TAG_B");

Fragment A -> Fragment B [onBackPressed] -->Fragment A

在Activity文件中重写onBackPressed(),检查是否处于Fragment B并正在查看该Fragment B。

if (getSupportFragmentManager().findFragmentByTag("TAG_B")!=null)  
{
    fragmentTransaction.replace(R.id.main_fragment_container, new FragmentA(),"TAG_A");
}

addToBackStack("TAG")和popBackStackImmediate("TAG")总是在将片段创建或添加到活动之前,将界面中没有任何数据的状态恢复为片段条件!


0
问题在于你的代码顺序。这里有两件事情你需要注意。
  1. 在添加或替换Fragment后,需要使用addToBackStack(),然后再commit()

  2. 然后使用popBackStackImmediate可以撤销操作,它是有效的。我希望这可以解决问题。我知道这是一个旧帖子,但我遇到了类似的问题,希望这个更新可以帮助其他人。下面应该是正确的顺序:

    FragmentTransaction fragmentTransaction =getSupportFragmentManager().beginTransaction();

    fragmentTransaction.replace(R.id.main_fragment_container, new FragmentB());
    
    fragmentTransaction.addToBackStack(null);
    
    fragmentTransaction.commit();
    

-1

如果你在处理addToBackStack()和popBackStack()时感到困难,那么可以简单地使用

FragmentTransaction ft =getSupportFragmentManager().beginTransaction();
ft.replace(R.id.content_frame, new HomeFragment(), "Home");
ft.commit();`

在您的Activity中,在OnBackPressed()方法里通过标签找到Fragment,然后进行您需要的操作。
Fragment home = getSupportFragmentManager().findFragmentByTag("Home");

if (home instanceof HomeFragment && home.isVisible()) {
    // do you stuff
}

更多信息请参考 https://github.com/DattaHujare/NavigationDrawer。我从未使用 addToBackStack() 处理片段。


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