从返回栈中移除一个碎片

78
当平板竖屏时,我的活动中有3个片段。但是当横屏时,我只有其中的2个片段。问题出现在从竖屏切换到横屏时,活动会创建第3个片段。因为该片段在后台堆栈中,所以会收到错误提示无法创建该片段。
我已经发现这个片段是因为它在后台堆栈中而被创建的。
我尝试在onDestroy方法中使用以下代码来删除该片段:
FragmentTransaction f = fragmentManager.beginTransaction();
f.remove(mf);
f.commit();

然而我收到一个错误,说在 onSaveInstanceState 后就不能再使用此函数。

如何正确地将此片段从后退栈中移除?

更新

我应该补充一下,我遇到问题的片段是来自这个库的 mapFragment。

https://github.com/petedoyle/android-support-v4-googlemaps

我使用它的方式如下:

mf = MapFragment.newInstance(1, true);

ft = fragmentManager.beginTransaction();
ft.replace(R.id.mapContainer, mf);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
ft.addToBackStack("map");
ft.commit();

1
你只需要删除 ft.addToBackStack(“map”) 这一行。 - M.Usman
5个回答

185
你可以使用FragmentManager的弹出方法将状态从后退栈中移除,并通过FragmentTransaction向后退栈添加状态:
FragmentManager manager = getActivity().getSupportFragmentManager();
FragmentTransaction trans = manager.beginTransaction();
trans.remove(myFrag);
trans.commit();
manager.popBackStack();

70
如果您想要移除的片段不在堆栈的顶部,会发生什么? - Kuno
3
是啊,当片段不在堆栈的顶部时,我很累不想工作。 还在努力弄清楚这个问题! - AJit
你找到那个问题的解决方案了吗? - An-droid
3
如果你事先知道该片段不应该成为返回栈的一部分,那么你可能会省略 "addToBackStack(null)"。 - marktani
6
我想知道为什么在执行 remove 操作后我还需要调用 manager.popBackStack()。我本以为只有 remove 事务就可以把它移除掉了,谢谢。 - j2emanue
显示剩余2条评论

24

我创建了一段代码,用于跳转到所需的后退栈索引,在我的目的上它运行良好。

即,我有Fragment1、Fragment2和Fragment3,我想从Fragment3跳转到Fragment1。

我在Fragment3中创建了一个名为onBackPressed的方法,用于跳转到Fragment1。

Fragment3:

public void onBackPressed() {
    FragmentManager fragmentManager = getFragmentManager();
    fragmentManager.popBackStack(fragmentManager.getBackStackEntryAt(fragmentManager.getBackStackEntryCount()-2).getId(), FragmentManager.POP_BACK_STACK_INCLUSIVE);
}
在这个活动中,我需要确定当前的片段是否为Fragment3,因此我调用我的片段的onBackPressed而不是调用super。 片段活动:
@Override
public void onBackPressed() {
    Fragment f = getSupportFragmentManager().findFragmentById(R.id.my_fragment_container);
    if (f instanceof Fragment3)
    {
        ((Fragment3)f).onBackPressed();
    } else {
        super.onBackPressed();
    }
}

4
如果碎片数量很多,代码会变得混乱,对吗?(我有20个碎片) - Kathir
val backPressController = currentFragment as? BackPressController ?: return handleBackPress()val shouldPerformBackPress = backPressController.onBackPressed() if (shouldPerformBackPress) handleBackPress() 请将以上程序相关内容翻译成中文。仅返回翻译后的文本。 - Tamim Attafi

2
您可以在容器(id为fragmentcontainer)中显示片段,因此您可以使用以下代码删除片段:
 Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.fragmentContainer);
            fragmentTransaction.remove(fragment);
            fragmentTransaction.addToBackStack(null);
            fragmentTransaction.commit();

java.lang.IllegalStateException: 此事务已经被添加到后退栈中 - Tamim Attafi

0

-13

24
我认为这是错误的,如果你读文档的话,“...所有状态直到那个状态”都会被弹出,所以它不会精确地移除那个片段,它将移除栈顶上的所有内容(根据标志还包括片段本身)。 - User
1
我不明白为什么人们会踩Dornathal的回答,却点赞@lxx的评论!这就是栈的工作方式按定义 - iSWORD
2
@iSWORD 因为问题还意味着如何仅删除不在顶部的一个片段。 - teh.fonsi

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