Android - 限制后退栈中片段的数量?

8

目前我只有一个活动,而片段正在被添加到它上面(搜索、歌曲详情、设置等)。我实现了基于侧边菜单的导航,因此,作为副作用,没有限制可以添加多少片段到后退栈中。有没有办法限制片段的数量或删除旧的条目?例如,每个歌曲详情片段都有一个推荐的歌曲列表,通过它可以进入另一个歌曲详情片段。很容易在后退栈中有30个片段,如果你打开DDMS,你会看到堆大小缓慢(但肯定)增加。

编辑:我尝试做的一件事是,如果用户点击侧边菜单选项之一,如果该片段已经在后退栈中,则尝试返回到该片段而不是实例化一个新的片段,但是,如果用户在歌曲详情页面上,则他希望按返回键回到该片段,所以这种方法行不通。

编辑2:这是我的addFragment方法(以及Phil的建议):

public void addFragment(Fragment fragment) { 

        FragmentManager fm = getSupportFragmentManager();
        if(fm.getBackStackEntryCount() > 2) {

              fm.popBackStack();
            }
        fm.beginTransaction()                 
                  .replace(R.id.fragment_container, fragment).addToBackStack("")
                  .commit();
}

我刚试了一下,假设我的 Fragment 历史记录是:A->B->C->D,从 D 返回,会经过 B->A->退出。

我刚刚进行了 8 层深度测试:A->B->C->D->E->F->G->H,从 H 返回,同样的事情发生了:H->B->A->退出。

所有的 Fragment 都是通过上述方法添加的。我想看到的是:H->G->F->退出。

3个回答

12

你可以以编程方式控制BackStack中Fragment的数量:

FragmentManager fm = getActivity().getSupportFragmentManager();

if(fm.getBackStackEntryCount() > 10) {

   fm.popBackStack(); // remove one (you can also remove more)
}

只需检查您的后堆栈中有多少个碎片,如果存在“溢出”,则将其删除。

如果要从BackStack中删除特定的Fragment,您将需要实现自己的BackStack并重写onBackPressed()方法。由于Fragment BackStack是一个堆栈(顾名思义),因此只能删除顶部元素(最后添加的元素),无法删除中间的Fragments。

例如,您可以使用

ArrayList<Fragment>

实现自己的“堆栈”很简单,只需从中添加和删除片段即可(这不再是一个真正的堆栈)。每当需要时,通过重写onBackPressed()方法来处理上一个片段的加载。


我的myFrag 是从哪里来的?假设我在准备添加新的 Fragment 时运行此代码,我是否已经必须拥有对所有先前 Fragment 的引用? - StackOverflowed
这只是一个示例代码,myFrag 可以是当前活动的 Fragment。在 if 语句中直接调用 fm.popBackStack() 也可以使用此代码。 - Philipp Jahoda
1
看起来你走在了正确的轨道上,但我希望最老的片段被删除。请参见编辑以获得澄清。到目前为止,非常感谢你的帮助。 - StackOverflowed
请查看我的编辑答案,我非常确定没有办法从BackStack中删除特定的Fragment。但是实现自己的“堆栈”应该很容易。 - Philipp Jahoda

3
这是一个老问题,但我的答案可能会对某些人有所帮助。为什么不检查片段是否在堆栈中并将其弹出?这样你就不必担心后退堆栈的大小了(除非你有很多片段)。
    String backStateName = fragment.getClass().getName();
    boolean fragmentPopped = false;
    try {
        // true if fragment is in the stack
        fragmentPopped = fragmentManager.popBackStackImmediate(backStateName, 0);
    } catch (Exception e) {
        e.printStackTrace();
    }

    FragmentTransaction ft = fragmentManager.beginTransaction();

    if ( !fragmentPopped ) { //fragment not in back stack, add it...            
        ft.setTransition( FragmentTransaction.TRANSIT_FRAGMENT_FADE );
        ft.replace(R.id.main, fragment);
        ft.addToBackStack( backStateName );

        try {
            ft.commit();
        } catch (Exception e) {
            e.printStackTrace();
        }           
    }

1

对于仍在寻找解决方案的人,可以尝试这个。在添加片段之前放置此代码。代码使用 Kotlin 编写。

val c = supportFragmentManager.backStackEntryCount-1
if(c > -1){
  for(i in 0 until c) {
    val entry = supportFragmentManager.getBackStackEntryAt(i)
    if(entry.name =="name used for commit") {
      supportFragmentManager.popBackManager(entry.id,0)
      return
    }
  }
}

...其他代码在这里...


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