碎片和后台有时会混乱

时间:2015-06-03 11:02:45

标签: android fragment fragment-backstack fragmentmanager

我有一个带有容器片段和NavigationDrawer的活动。如果我在抽屉中选择一个项目,我会拨打updatePage(index)

如果我创建活动,我也会调用updatePage(0),而savedInstanceState == null则会调用我的活动。

一个片段有一个子片段,因此它只是通过子片段替换自己,并将子片段添加到backstack,以便用户可以导航回到前一个片段。在这个片段中,我直接调用以下代码:

@Override
public void onClick(View view)
{
    Event event = (Event)view.getTag();

    FragmentManager fm = getActivity().getSupportFragmentManager();

    GamesFragment f = new GamesFragment();

    Bundle bundle = new Bundle();
    bundle.putParcelable(GamesFragment.KEY_EVENT, event);
    f.setArguments(bundle);

    FragmentTransaction ft = fm.beginTransaction()
            .replace(R.id.frame_container, f, f.getClass().getName())
            .addToBackStack(null);
    ft.commit();
}

为什么有时删除旧片段不起作用?我得到了重叠片段,但有时只是。

我的活动updatePage功能如下:

private void updatePage(int drawerSelection)
{
    mDrawer.closeDrawer();

    Fragment f = null;
    FragmentManager fm = getSupportFragmentManager();

    switch (drawerSelection)
    {
        case 0:
            f = fm.findFragmentByTag(HomeFragment.class.getName());
            if (f == null)
                f = new HomeFragment();
            break;
        case 1:
            f = fm.findFragmentByTag(EventFragment.class.getName());
            if (f == null)
                f = new EventFragment();
            break;
        default:
            break;
    }

    if (f != null && !f.isAdded())
    {
        // SOLUTION:
        // Backstack clearen
        // fm.popBackStackImmediate(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
        FragmentTransaction ft = fm.beginTransaction();
        ft.replace(R.id.frame_container, f, f.getClass().getName());
        ft.commit();
    }
}

2 个答案:

答案 0 :(得分:1)

我几次看到这种情况,我敢打赌用addToBackStack替换后可能会发生这种情况。最简单的修复方法是为片段布局添加背景。来自android doc:

  

注意:删除或替换片段并将事务添加到后台堆栈时,将删除(不销毁)已删除的片段。如果用户导航回还原片段,则会重新启动。如果您不将事务添加到后台堆栈,则在删除或替换时会破坏该片段。

此视图不会完全重新绘制,如果第二个片段没有背景或视图容器重绘,您将获得所描述的效果。这是我的理论:>。有时Android文档并不像我们希望的那样清晰。

答案 1 :(得分:1)

问题出在以下用例:

EventFragment转到GameFragment推送"删除(EventFragment).add(GameFragment)"交易到后台。如果我现在按下后退按钮,此交易将被撤消,一切都很好。后躯再次空着,一切正常。但是,如果我不按后退按钮,但通过菜单更改为另一个片段,则后台堆栈仍然具有上述交易。现在回过头来尝试撤销这个事务...它会在菜单点击处理程序中的代码添加菜单中的片段之前读取EventFragment ...这就是它可能发生的方式......

简单的解决方案,如果我只需要为每个菜单条目添加一个backstack并想要删除backstack,如果我在菜单中选择我的应用程序的另一个区域,则在我通过菜单进入另一个区域之前清除backstack。 ..

所以添加' fm.popBackStackImmediate(null,FragmentManager.POP_BACK_STACK_INCLUSIVE);'在替换当前片段之前将解决问题(我将此解决方案添加为对我主帖的评论)