使用片段清除后台堆栈

我将自己的Android应用移植到honeycomb上,为了使用fragments,我做了一次大的重构。在我以前的版本中,当我按下Home按钮时,我经常执行ACTIVITY_CLEAR_TOP以重置back堆栈。

现在我的应用程序只是一个具有多个片段的单个活动,所以当我按下Home按钮时,我只是替换其中一个片段。如何在不使用带有ACTIVITY_CLEAR_TOP标志的startActivity的情况下清除back堆栈?

276843 次浏览

我在这里张贴了类似的东西

来自约阿希姆的回答,来自Dianne Hackborn:

http://groups.google.com/group/android-developers/browse_thread/thread/d2a5c203dad6ec42

最后我只用了:

FragmentManager fm = getActivity().getSupportFragmentManager();
for(int i = 0; i < fm.getBackStackEntryCount(); ++i) {
fm.popBackStack();
}

但同样可以使用类似的东西:

((AppCompatActivity)getContext()).getSupportFragmentManager().popBackStack(String name, FragmentManager.POP_BACK_STACK_INCLUSIVE)

这将弹出所有的状态到指定的一个。然后你可以用你想要的东西替换这个片段

接受的答案对我来说是不够的。我不得不使用:

FragmentManager fm = getSupportFragmentManager();
int count = fm.getBackStackEntryCount();
for(int i = 0; i < count; ++i) {
fm.popBackStackImmediate();
}

为@Warpzit的评论做一个回答,让其他人更容易找到。

使用:

fragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);

我让它这样工作:

public void showHome() {
getHandler().post(new Runnable() {
@Override
public void run() {
final FragmentManager fm = getSupportFragmentManager();
while (fm.getBackStackEntryCount() > 0) {
fm.popBackStackImmediate();
}
}
});
}

在尊重所有相关方的前提下;我非常惊讶地看到你们中有多少人可以用一个简单的方法清除整个片段返回堆栈

fm.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);

根据安卓系统文档(关于name参数-声称的工作建议中的“null”)。

如果为空,则只弹出顶部状态

现在,我确实意识到我对你的特定实现缺乏了解(比如在给定的时间点你在后台堆栈中有多少项),但当我期待在更广泛的设备和供应商上有良好定义的行为时,我会把我所有的钱都押在公认的答案上:

(作为参考,和这个一起)

FragmentManager fm = getFragmentManager(); // or 'getSupportFragmentManager();'
int count = fm.getBackStackEntryCount();
for(int i = 0; i < count; ++i) {
fm.popBackStack();
}

清除无循环的backstack

String name = getSupportFragmentManager().getBackStackEntryAt(0).getName();
getSupportFragmentManager().popBackStack(name, FragmentManager.POP_BACK_STACK_INCLUSIVE);

哪里的名字是addToBackStack()参数

getSupportFragmentManager().beginTransaction().
.replace(R.id.container, fragments.get(titleCode))
.addToBackStack(name)

工作为我和简单的方法不使用循环:

 FragmentManager fragmentManager = getSupportFragmentManager();
//this will clear the back stack and displays no animation on the screen
fragmentManager.popBackStackImmediate(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);

我只想补充一点:——

使用下面的方法从后台弹出

fragmentManager.popBackStack ()

只是关于从交易中删除片段,它不可能从屏幕上删除片段。 所以理想情况下,你可能看不到它,但可能有两三个片段堆叠在一起,按下后退键UI可能看起来很杂乱,堆叠起来

举个简单的例子:-

假设你有一个fragmentA,它使用fragmentmanager.replace ()加载Fragmnet B,然后我们做addToBackStack,来保存这个事务。 所以流程是:——

step1 -> FragmentA->FragmentB(我们移动到FragmentB,但FragmentA在背景中,不可见)。

现在你在fragmentB中做了一些工作,并按下Save按钮——保存后应该回到fragmentA。

在FragmentB保存时,我们返回FragmentA。

常见的错误是……在Fragment B中,我们将执行Fragment Manager.replace() fragmentB与fragmentA。

但实际发生的是,我们再次载入片段A,取代片段b。所以现在有两个FragmentA(一个来自step1,一个来自step3)。

FragmentsA的两个实例堆叠在一起,它们可能不可见,但确实存在。

因此,即使我们通过上述方法清除了后台堆栈,也会清除事务,但不会清除实际的片段。 所以在这种特殊情况下,理想情况下,在按下保存按钮时,你只需要通过简单地执行fm.popBackStack ()fm.popBackImmediate ().

来返回fragmentA

所以纠正Step3-> fm.popBackStack()回到fragmentA,它已经在内存中了。

读取文档并研究片段id是什么,它似乎只是堆栈索引,所以这是可行的:

fragmentManager.popBackStackImmediate(0, FragmentManager.POP_BACK_STACK_INCLUSIVE);

Zero (0)是堆栈的底部,所以弹出到它包含清空堆栈。

警告:尽管上面的代码在我的程序中是有效的,但我还是有些犹豫,因为FragmentManager文档从来没有真正声明id是堆栈索引。这是有道理的,我所有的调试日志都表明它是,但也许在某些特殊情况下它不是?有人能证实这一点吗?如果是,那么以上是最好的解决方案。如果不是,这是另一种选择:

while(fragmentManager.getBackStackEntryCount() > 0) { fragmentManager.popBackStackImmediate(); }

只需使用此方法并传递Context &片段标签,直到我们需要删除背桩片段。

使用

clearFragmentByTag(context, FragmentName.class.getName());






public static void clearFragmentByTag(Context context, String tag) {
try {
FragmentManager fm = ((AppCompatActivity) context).getSupportFragmentManager();


for (int i = fm.getBackStackEntryCount() - 1; i >= 0; i--) {
String backEntry = fm.getBackStackEntryAt(i).getName();
if (backEntry.equals(tag)) {
break;
} else {
fm.popBackStack();
}
}
} catch (Exception e) {
System.out.print("!====Popbackstack error : " + e);
e.printStackTrace();
}
}
    private void clearBackStack(){
SupportFragmentManaer fm = getSupportFragmentManager();
fm.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
}

调用这个方法会非常简洁。

  1. 不需要循环。
  2. 如果你在片段中使用动画,它不会显示太多动画。但是使用循环会。
private boolean removeFragFromBackStack() {
try {
FragmentManager manager = getSupportFragmentManager();
List<Fragment> fragsList = manager.getFragments();
if (fragsList.size() == 0) {
return true;
}
manager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
return true;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}

嗨~我找到了一个更好的解决方案,从:https://gist.github.com/ikew0ng/8297033

    /**
* Remove all entries from the backStack of this fragmentManager.
*
* @param fragmentManager the fragmentManager to clear.
*/
private void clearBackStack(FragmentManager fragmentManager) {
if (fragmentManager.getBackStackEntryCount() > 0) {
FragmentManager.BackStackEntry entry = fragmentManager.getBackStackEntryAt(0);
fragmentManager.popBackStack(entry.getId(), FragmentManager.POP_BACK_STACK_INCLUSIVE);
}
}

这对我很有效,试试这个:

public void clearFragmentBackStack() {
FragmentManager fm = getSupportFragmentManager();
for (int i = 0; i < fm.getBackStackEntryCount() - 1; i++) {
fm.popBackStack();
}
}

这里的kotlin人

repeat(supportFragmentManager.backStackEntryCount) {
supportFragmentManager.popBackStack()
}