防止同一片段重复堆叠(addToBackStack)

7

我有一个Activity,其中包含三个片段,我们称它们为ABC。在ActivityonCreate()方法中调用FragmentA

FragmentA fragA = new FragmentA();
FragmentTransaction transaction = manager.beginTransaction();
transaction.add(R.id.activity2_layout, fragA, "A");
transaction.commit();

当某些按钮被按下并且FragmentTransaction调用了addToBackStack()时,会将其替换为FragmentBC

FragmentB fragB = new FragmentB(); //or C
FragmentTransaction transaction = manager.beginTransaction();
transaction.replace(R.id.activity2_layout, fragB, "B");  //or C
transaction.addToBackStack("B"); //or C
transaction.commit();

现在假设我连续三次调用Fragment B,如何防止它自己堆叠?同时我希望这种情况是可能的:B 被调用 > C 被调用 > B 被调用 - 但当我尝试返回时,我希望只打开B一次 (C < B) 而不是 (B < C < B)。因此基本上要用新的BackStack替换第一个BackStack。

2个回答

13

如何在存在的情况下从BackStack恢复Fragment,这可能与您的查询非常相似。

有一种方法可以基于事务名称或由提交提供的id弹出后退堆栈(例如,使用Fragment的类名,如Thijs已经提到的):

String backStateName = fragment.getClass().getName();

添加到返回栈:

FragmentTransaction ft = manager.beginTransaction();
ft.replace(R.id.content_frame, fragment);
ft.addToBackStack(backStateName);
ft.commit();

当爆炸时:

getSupportFragmentManager().popBackStackImmediate (backStateName, 0); 

因此,在替换片段之前,我们可以像这样在后退栈中检查其是否存在:

boolean fragmentPopped = manager.popBackStackImmediate (backStateName, 0);

if (!fragmentPopped){ //fragment not in back stack, create it.
    ...
    ...
    ft.addToBackStack(backStateName);
    ft.commit();
}
请查看上述问题和被接受的答案以获取更多解释。

这是更好的答案,因为它回答了两个问题 :) - Thijs Koppen

1
我曾经在自己的项目中解决过你的一个问题,即如何防止它自身堆叠?以下是我当时使用的代码:
public void setContent(@NonNull Fragment fragment, boolean addToBackStack) {
    Fragment current = getSupportFragmentManager().findFragmentById(R.id.main_content);
    if (current == null || !current.getClass().equals(fragment.getClass())) {
        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
        if (addToBackStack) {
            transaction.addToBackStack(null).add(R.id.main_content, fragment).commit();
        } else {
            transaction.replace(R.id.main_content, fragment).commit();
        }
    }
}

这段代码的作用是检查当前显示的片段属于哪个类,并将其与要替换的片段进行比较。如果它们相同,则不执行任何操作。此代码可根据您的需要进行调整。
Fragment newFragment = new FragmentB(); //OR FragmentC
Fragment current = getSupportFragmentManager().findFragmentById(R.id.activity2_layout);
if (!current.getClass().equals(newFragment.getClass())) {

    //POP BACKSTACK HERE LIKE EXPLAINED BELOW

    FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
    final String tag = newFragment.getClass().getSimpleName();
    transaction.addToBackStack(tag);
    transaction.add(R.id.activity2_layout, newFragment, tag);
    transaction.commit();
} else {
    //THROW AN ERROR OR SOMETHING, HANDLE IT BEING THE SAME
}

确保同一类型的片段一次只出现一个,可能通过弹出回退栈直到第一个相同片段之前来实现。我没有为此编写任何代码,但实现这个功能应该不太困难。如果您无法自行解决,请告诉我,我会尝试为您编写示例 :)


谢谢 :) 不需要示例 :) 我现在唯一需要解决的问题是如何删除已经存在的后退栈,如果可能的话,因为我找不到任何关于它的文档或示例。 - Ivan Javorovic
1
我认为这根本不可能。据我所知,FragmentManager 只有一个后退栈。您可以弹出条目,然后添加另一个条目以用一个新条目“替换”该数量的条目。只要在 commit() 之前这样做,就应该没问题 :) - Thijs Koppen
@IvanJavorovic,您说的“remove backStacks”是指清除后退栈吗? - Abu Ruqaiyah

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