Android Reorder Fragment Backstack [英] Android Reorder Fragment Backstack

查看:27
本文介绍了Android Reorder Fragment Backstack的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a number of pages/fragments listed in my navigation drawer, the user is likely to switch between these frequently and I want them in the backstack so that they can navigate back, but I only want one instance of each fragment in the backstack so that the user doesn't not have to press back an insane number of times to exit the app. I can't figure out how to effectively 'reorder' the backstack' without pages getting removed.

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

Currently when I change page I was using this code to change the fragment and make sure it's only in the back stack once

  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();
  }

我在 onBackPressed 中使用此代码

I use this code in onBackPressed

  @Override
  public void onBackPressed() {
      if (mFragMgr.getBackStackEntryCount() > 0) {
          mFragMgr.popBackStackImmediate();
      } else {
          super.onBackPressed();
      }
  }

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

This works but it means it removes pages I don't want removed. Example:

当我的用户按 A > 的顺序访问 6 个页面时乙>C>D>E>C 因为我正在做一个删除我期望以下堆栈:

When my user visits 6 pages in the order A > B > C > D > E > C because I'm doing a remove I expected the following stack:

                            [E]    [C]
                     [D]    [D]    [E]
              [C]    [C]    [C]    [D]
       [B]    [B]    [B]    [B]    [B]
[A] -> [A] -> [A] -> [A] -> [A] -> [A]

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

But what I actually get is the following - it pops everything up to the element that matches the name, this is regardless of whether I include the ".remove((Fragment) mFragment)" or not - (I've already realised now that remove isn't affecting the backstack, so no need to point that out):

                            [E]
                     [D]    [D]
              [C]    [C]    [C]    [C]
       [B]    [B]    [B]    [B]    [B]
[A] -> [A] -> [A] -> [A] -> [A] -> [A]

如果我在添加到后台堆栈时不使用名称而是使用 null,我会得到以下结果:

If I don't use a name and instead use null when adding to the backstack I get the following:

                                   [C]
                            [E]    [E]   
                     [D]    [D]    [D]    
              [C]    [C]    [C]    [C]   
       [B]    [B]    [B]    [B]    [B]  
[A] -> [A] -> [A] -> [A] -> [A] -> [A] 

我怎样才能得到我期望的行为?是否有可能,还是我需要自己记录更改并完全跳过 backstack?

How can I get the behaviour I expect? Is it possible at all or am I going to need to record the changes myself and skip the backstack altogether?

推荐答案

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

There is no API to do this, but becuse I was wondering the same thing last week,
I took it as an exercise an implemented it myself.

我的方法允许您从 backstack 中的任何位置删除 Fragment,这是通过使用反射修改存储在 FragmentManagerImplBackStackRecord.

My method allows you to remove a Fragment from anywhere in the backstack and this is achieved by using refrection to modify the internal variables that store the backstack information in FragmentManagerImpl and BackStackRecord.

有几个重要的变量:

  • mBackStack - 存储保存 Fragment 信息、以前的、动画等的 BackStackRecords
  • mActive - 所有添加的 Fragments
  • mAvailBackStackIndices - 存储新插入记录可以使用的索引,即 mActive
  • null 值的索引
  • 和其他
  • mBackStack - stores the BackStackRecords that hold the Fragment info, the previous ones, animations, etc
  • mActive - all added Fragments
  • mAvailBackStackIndices - stores the indices that can be used by the newly inserted records, i.e. indices of null values in mActive
  • and other

使用 150 多个 Fragment 进行测试,未发现任何泄漏,但仅监控 DDMS 中的堆,未执行任何其他内存分析.
因此,因为某些事情可能会被破坏,请探索代码,重新测试它,看看是否有人提供了更好的答案,并重新考虑您是否真的需要在您的项目中执行此操作.

Tested with 150+ Fragments and couldn't notice any leaks, but only monitored the heap in DDMS and did not perform any other memory analysis.
So because someting may be broken, explore the code, re-test it, see if anyone provides a better answer, and rethink if you really need to do this in your project.

我将代码作为 GitHub 上的要点上传,希望对您有所帮助.

I uploaded the code as a gist on GitHub, hope it helps.

这篇关于Android Reorder Fragment Backstack的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆