问题描述
我的导航抽屉中列出了许多页面/片段,用户可能会经常在这些页面/片段之间切换,我希望它们在后台堆栈中以便他们可以返回,但我只想要每个片段的一个实例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
,这是通过使用反射修改存储在 FragmentManagerImpl 和 BackStackRecord.
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
信息、以前的、动画等的BackStackRecord
smActive
- 所有添加的Fragment
smAvailBackStackIndices
- 存储新插入记录可以使用的索引,即mActive
中 - 和其他
null
值的索引mBackStack
- stores theBackStackRecord
s that hold theFragment
info, the previous ones, animations, etcmActive
- all addedFragment
smAvailBackStackIndices
- stores the indices that can be used by the newly inserted records, i.e. indices ofnull
values inmActive
- and other
使用 150 多个 Fragment
进行测试,未发现任何泄漏,但仅监控 DDMS
中的堆,未执行任何其他内存分析.
因此,因为某些事情可能会被破坏,请探索代码,重新测试它,看看是否有人提供了更好的答案,并重新考虑您是否真的需要在您的项目中执行此操作.
Tested with 150+ Fragment
s 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的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!