Android片段在方向更改时重新创建

17

我正在开发一个具有ActionBar的应用程序。当我的应用程序启动时,Activity会创建片段并将它们附加到每个选项卡,所以当我切换时,我会得到不同的视图。

问题出现在我尝试旋转设备时。经过一些努力,我注意到Android会自动重新创建之前添加的片段,方法如下:

SummaryFragment.onCreate(Bundle) line: 79   
FragmentManagerImpl.moveToState(Fragment, int, int, int) line: 795  
FragmentManagerImpl.moveToState(int, int, int, boolean) line: 1032  
FragmentManagerImpl.moveToState(int, boolean) line: 1014    
FragmentManagerImpl.dispatchCreate() line: 1761 
DashboardActivity(Activity).onCreate(Bundle) line: 864  
...

然后像往常一样重新创建片段。所以我有了我期望能够正确工作的“真实”片段和它们由Android创建的“隐藏”对应物,这使得我的应用程序崩溃。我该如何避免这种行为?我已经尝试在SummaryFragment中调用setRetainInstance(false)。

谢谢

4个回答

42

你需要检查 savedInstanceState [编辑:在父活动中] 是否存在,如果存在,则不要创建你的片段。

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    if (savedInstanceState == null) {
         // Do your oncreate stuff because there is no bundle   
    }
// Do stuff that needs to be done even if there is a saved instance, or do nothing
}

1
不确定这是否是OP遇到的同样问题,但对我来说非常有用。谢谢。 - ssmy
非常感谢@Barak,只有他的解决方案在一周后才起作用。 - Pavan kumar

0

我不确定是否有更好的解决方案,但这是我在最新程序中所做的。

当系统在屏幕方向改变时自动创建一个片段,并且您想要在主活动中跟踪它们时,请在主活动的OnAttachFragment()方法中捕获它们。它们默认会获取参数,因此您可以使用它们来找出它是哪个片段。

   public void onAttachFragment(Fragment fragment) {
    super.onAttachFragment(fragment);
    if (fragment != null) {
        if(fragment.getArguments() != null) {
            switch (fragment.getArguments().getString(ARG_PARAM1)) {
                case FragmentATag:
                    if (myFragmentA != fragment) {
                        myFragmentA = (FragmentA) fragment;
                    }                     
                    break;
                case FragmentBTag:
                    if (myFragmentB != fragment) {
                        myFragmentB = (FragmentB) fragment;
                    }                        
                    break;                  
            }
        }
     }
   }

0
创建活动时,请检查它是否已经存在。如果存在,则无需做任何操作...Android 会为您重新创建它。
private void initFragment() {
        FragmentManager fragMgr = getSupportFragmentManager();
        if (fragMgr.findFragmentByTag(LEADERBOARD_FRAG_TAG) != null) { return; }
        frag = new HdrLeaderboardFragment();
        FragmentTransaction ft = fragMgr.beginTransaction();
        ft.replace(R.id.leaderboard_fragment_wrapper, frag, LEADERBOARD_FRAG_TAG);
        ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
        ft.commit();
    }

1
这样做仍然会添加两个Fragment...一个是我已经有的(按照你建议的方式),另一个让我简直要发疯。在方向更改之间重置FragmentManager本来很容易的。 - Luke47

0
如果你对于两种方向都有类似的UI(没有特定的layout-land文件),你可以在清单文件中将android:configChanges="keyboardHidden|orientation"设置到活动中。
如果你没有提供源代码来添加片段到标签页,我会尝试帮助你进行改进。

部分问题已经通过你的答案解决了。由于大部分绘图都是动态完成的,我移除了所有视图并根据新的方向重新布局它们。说实话,我认为这不是一个干净的解决方案,但我无法阻止系统为我疯狂地创建片段... - Luke47
这对我很有帮助,因为我总是忘记在更改纵向布局后更新我的横向布局文件。这已经发生了大约5次了。 - buster
3
当将设备插入汽车坞、电视或进行任何其他配置更改时,会发生不好的事情:碎片仍然会被重建。android:configChanges很危险,除非你真的知道自己在做什么。 - personne3000

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