使用碎片清除后堆叠

问题描述

| 我将Android应用程序移植到蜂窝上,为了使用片段,我做了很大的重构。在以前的版本中,当我按下“主页”按钮时,我曾经做过一个“ 0”以重置后退纸叠。 现在我的应用只是一个带有多个片段的Activity,因此当我按下Home按钮时,我只是替换了其中的一个片段。如何在不使用
ACTIVITY_CLEAR_TOP
标志的情况下清除stack栈?     

解决方法

        我在这里贴了类似的东西 根据约阿希姆的回答,来自黛安·哈克伯恩(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)
这会将所有状态弹出到指定状态。然后,您可以将片段替换为所需的片段     ,        为@Warpzit的评论提供答案,并使其他人更容易找到。 采用:
fragmentManager.popBackStack(null,FragmentManager.POP_BACK_STACK_INCLUSIVE);
    ,        充分尊重所有有关方面;我很惊讶地看到你们中有多少人可以通过简单的操作清除整个碎片
fm.popBackStack(null,FragmentManager.POP_BACK_STACK_INCLUSIVE);
根据Android文档(关于
name
参数-所主张的工作建议中的\“ null \”)。   如果为null,则仅弹出最高状态 现在,我的确意识到我对您的特定实现缺乏了解(例如,在给定的时间点,您在后台堆栈中有多少个条目),但是我希望所有的钱都花在接受的答案上,希望得到一个好的结果在更广泛的设备和供应商中定义的行为: (供参考,与此同时)
FragmentManager fm = getFragmentManager(); // or \'getSupportFragmentManager();\'
int count = fm.getBackStackEntryCount();
for(int i = 0; i < count; ++i) {    
    fm.popBackStack();
}
    ,        接受的答案对我来说还不够。我不得不使用:
FragmentManager fm = getSupportFragmentManager();
int count = fm.getBackStackEntryCount();
for(int i = 0; i < count; ++i) {
    fm.popBackStackImmediate();
}
    ,        为我工作,不使用循环的简单方法:
 FragmentManager fragmentManager = getSupportFragmentManager();
 //this will clear the back stack and displays no animation on the screen
 fragmentManager.popBackStackImmediate(null,FragmentManager.POP_BACK_STACK_INCLUSIVE);
    ,        清除没有循环的堆栈
String name = getSupportFragmentManager().getBackStackEntryAt(0).getName();
getSupportFragmentManager().popBackStack(name,FragmentManager.POP_BACK_STACK_INCLUSIVE);
其中name是addToBackStack()参数
getSupportFragmentManager().beginTransaction().
                .replace(R.id.container,fragments.get(titleCode))
                .addToBackStack(name)
    ,        我只想补充:- 使用以下命令从堆栈弹出   fragmentManager.popBackStack() 只是要从事务中删除碎片,而无法从屏幕上删除碎片。 因此,理想情况下,它可能对您不可见,但是可能有两个或三个片段彼此堆叠,并且在按回车键时,UI可能看起来很杂乱,堆叠。 仅举一个简单的例子: 假设您有一个fragmentA,它使用fragmentmanager.replace()加载Fragmnet B,然后执行addToBackStack来保存该事务。 所以流程是:- 步骤1-> FragmentA-> FragmentB(我们移至FragmentB,但是Fragment A在背景中,不可见)。 现在,您在fragmentB中进行一些工作,然后按“保存”按钮,保存后,该按钮应返回至fragmentA。 步骤2->保存FragmentB,然后返回FragmentA。 步骤3->所以常见的错误是...在片段B中,我们将使用片段A执行片段Manager.replace()片段B。 但是实际上发生了什么,我们再次加载Fragment A,代替FragmentB。因此,现在有两个FragmentA(一个来自STEP-1,一个来自此STEP-3)。 FragmentsA的两个实例彼此堆叠,这可能不可见,但在那里。 因此,即使我们确实通过上述方法清除了后栈,事务也会被清除,但不会清除实际的碎片。 因此,理想情况下,在这种情况下,只需按一下保存按钮,只需执行fm.popBackStack()或fm.popBackImmediate()即可返回fragmentA。 因此,正确的Step3-> fm.popBackStack()返回到已经在内存中的fragmentA。     ,        阅读文档并研究片段ID是什么,它似乎只是堆栈索引,因此可行:
fragmentManager.popBackStackImmediate(0,FragmentManager.POP_BACK_STACK_INCLUSIVE);
零(
0
)是堆栈的底部,因此弹出时将其包括在内会清除堆栈。 CAVEAT:尽管上面的代码在我的程序中有效,但我还是有些犹豫,因为FragmentManager文档从不实际声明id是堆栈索引。确实是这样,我的所有调试日志都没有,但是在某些特殊情况下不是吗?任何人都可以以一种或另一种方式确认这种情况吗?如果是这样,那么以上是最佳解决方案。如果没有,这是替代方案:
while(fragmentManager.getBackStackEntryCount() > 0) { fragmentManager.popBackStackImmediate(); }
    ,           只需使用此方法,然后传递Context&Fragment标签即可,我们需要删除该标签。 用法
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();
    }
}
    ,        嗨〜我找到了一个更好的解决方案,来自: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 showHome() {
    getHandler().post(new Runnable() {
        @Override
        public void run() {
            final FragmentManager fm = getSupportFragmentManager();
            while (fm.getBackStackEntryCount() > 0) {
                fm.popBackStackImmediate();
            }
        }
    });
}
    ,它对我有用,请尝试以下方法:
public void clearFragmentBackStack() {
        FragmentManager fm = getSupportFragmentManager();
        for (int i = 0; i < fm.getBackStackEntryCount() - 1; i++) {
            fm.popBackStack();
        }
    }
    ,        
    private void clearBackStack(){
        SupportFragmentManaer fm = getSupportFragmentManager();
        fm.popBackStack(null,FragmentManager.POP_BACK_STACK_INCLUSIVE);
    }
调用此方法将非常简洁。 无需循环。 如果您在片段中使用动画,它将不会显示太多动画。但是使用循环会。     ,        
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;
}