Android Reorder Fragment Backstack

Nic*_*oso 19 android android-fragments back-stack

我的导航抽屉中列出了许多页面/片段,用户可能经常在这些页面/片段之间切换,我希望它们在后台中,以便他们可以导航回来,但我只想在后台堆栈中每个片段的一个实例用户不必按下疯狂的次数退出应用程序.我无法弄清楚如何在没有删除页面的情况下有效地"重新排序"后台堆栈.

目前,当我更改页面时,我正在使用此代码更改片段并确保它仅在后面的堆栈中一次

  if (mFragMgr == null) {
      mFragMgr = getSupportFragmentManager();
  }

  String backStateName = fragmentDescriptor.name();
  boolean fragmentPopped = mFragMgr.popBackStackImmediate(backStateName, 0);
  if (!fragmentPopped){
      mFragMgr.beginTransaction()
      .remove((Fragment) mFragment)
      .replace(R.id.content_frame, (Fragment) mFragment)
      .addToBackStack(backStateName)
      .commit();
  }
Run Code Online (Sandbox Code Playgroud)

我在onBackPressed中使用此代码

  @Override
  public void onBackPressed() {
      if (mFragMgr.getBackStackEntryCount() > 0) {
          mFragMgr.popBackStackImmediate();
      } else {
          super.onBackPressed();
      }
  }
Run Code Online (Sandbox Code Playgroud)

这有效,但这意味着它删除了我不想删除的页面.例:

当我的用户在订单中访问6页A > B > C > D > E > C因为我正在进行删除时,我期望以下堆栈:

                            [E]    [C]
                     [D]    [D]    [E]
              [C]    [C]    [C]    [D]
       [B]    [B]    [B]    [B]    [B]
[A] -> [A] -> [A] -> [A] -> [A] -> [A]
Run Code Online (Sandbox Code Playgroud)

但实际得到的是以下内容 - 它会将所有内容弹出到与名称相匹配的元素,这与我是否包含".remove((Fragment)mFragment)"无关 - (我已经意识到了remove不会影响backstack,所以不需要指出那个):

                            [E]
                     [D]    [D]
              [C]    [C]    [C]    [C]
       [B]    [B]    [B]    [B]    [B]
[A] -> [A] -> [A] -> [A] -> [A] -> [A]
Run Code Online (Sandbox Code Playgroud)

如果我不使用名称,而是在添加到backstack时使用null,我会得到以下内容:

                                   [C]
                            [E]    [E]   
                     [D]    [D]    [D]    
              [C]    [C]    [C]    [C]   
       [B]    [B]    [B]    [B]    [B]  
[A] -> [A] -> [A] -> [A] -> [A] -> [A] 
Run Code Online (Sandbox Code Playgroud)

我怎样才能得到我期望的行为?是否有可能或我是否需要自己记录更改并完全跳过后台堆叠?

jan*_*ovd 22

没有API可以做到这一点,但是因为我上周想知道同样的事情,
我把它作为一个练习,我自己实现了它.

我的方法允许您Fragment从Backstack中的任何位置删除a ,这是通过使用refrection修改存储FragmentManagerImplBackStackRecord中的Backstack信息的内部变量来实现的.

几个重要变量:

  • mBackStack- 存储包含信息的BackStackRecords,Fragment以前的信息,动画等
  • mActive- 所有添加Fragment
  • mAvailBackStackIndices- 存储新插入记录可以使用的索引,即null值的索引mActive
  • 和别的

经过150多Fragment秒的测试,无法察觉任何泄漏,但只监控了堆,DDMS并没有执行任何其他内存分析.
因此,可能会破坏某些方法,探索代码,重新测试它,看看是否有人提供了更好的答案,并重新考虑是否真的需要在项目中执行此操作.

我上传了代码作为GitHub要点,希望它有所帮助.