保留片段状态

时间:2013-05-09 12:11:06

标签: android android-fragments

在我的应用中,我有以下架构:

MainActivity
|_ FirstFragment
|   |_ GridFragment
|   |_ MapFragment
|
|_ SecondFragment
|
|_ ThirdFragment

请注意:

  • MainActivity正在使用ActionBarSherlockSlidingMenu
  • SlidingMenu在片段之间切换(FirstFragmentSecondFragmentThirdFragment)。
  • FirstFragment在操作栏中创建一个按钮,可在网格地图模式之间切换。这是在其子片段之间切换。

我想要实现的目标

我需要片段在它们之间切换时需要保持其状态。这是,如果我在FirstFragment然后选择地图模式(显示MapFragment子碎片),并从幻灯片菜单中选择另一个选项并返回,我应该再次看到地图。现在,它正在从幻灯片菜单中选择其部分时重置每个片段。

这并不奇怪,因为当我按下菜单选项时,我正在提交与new FirstFragment()的交易。

但是,我首先尝试将每个片段引用到其父级中。例如,MainActivity有三个片段成员,当提交事务时,如果存在则检查它们是否存在,并在必要时进行实例化。这工作正常,直到我添加第二级片段,然后它在提交事务时开始抛出异常(说活动被销毁)。

您可能已经注意到,我远不是Android专家,需要一些关于此主题的指导。

如何在不为每个片段状态提供参考的情况下保留片段状态?

1 个答案:

答案 0 :(得分:4)

我在发布问题后尝试的另一件事是避免将片段保存在其容器内的局部变量中,并在任何给定时间使用FragmentManager.getFragmentByTag()来访问它们,但问题仍然存在,如FragmentTransaction.replace()正在摧毁这些碎片。

我的解决方案

正如 Luksprog 在他的评论中指出的那样,我必须手动管理所有片段。为了实现这一点,我不得不回到我以前的方法,在那里我有每个片段的局部变量。然后,MainActivity执行以下操作:

  • 实例化其三个片段。

    this.firstFragment = new FirstFragment();
    this.secondFragment = new SecondFragment();
    this.thirdFragment = new ThirdFragment();
    
  • 附上三个片段,并隐藏除初始部分以外的所有片段。

    getSupportFragmentManager()
        .beginTransaction()
        .add(R.id.content_frame, this.firstFragment)
        .add(R.id.content_frame, this.secondFragment)
        .add(R.id.content_frame, this.thirdFragment)
        .hide(this.secondFragment)
        .hide(this.thirdFragment)
        .commit();
    
  • 要切换内容,SlideMenu正在调用此功能:

    public void switchContent(Fragment newContent) {
        if (newContent != null) {
            getSupportFragmentManager()
            .beginTransaction()
            .detach(this.firstFragment)
            .detach(this.secondFragment)
            .detach(this.thirdFragment)
            .attach(newContent)
            .commit();
    
            // Restore menu open gesture if map is not present
            if (!(newContent instanceof firstFragment) &&  getSlidingMenu().getTouchModeAbove() != SlidingMenu.TOUCHMODE_FULLSCREEN)
                getSlidingMenu().setTouchModeAbove(SlidingMenu.TOUCHMODE_FULLSCREEN);
    
            // Set menu open gesture if map is present
            if (newContent instanceof firstFragment && firstFragment.currentFragment == FirstFragment.MAP_FRAGMENT)
                getSlidingMenu().setTouchModeAbove(SlidingMenu.TOUCHMODE_NONE);
    
            getSlidingMenu().showContent();
        }
    }
    

然后,具有子片段(FirstFragment)的片段也在做同样的事情但是:

  • 它使用getChildFragmentManager()代替getSupportFragmentManager()
  • 使用show()hide()替换内容,因为在使用detach()attach()时,地图并未保留其坐标。