一些碎片在旋转时丢失

时间:2013-05-25 22:16:39

标签: android rotation android-fragments android-lifecycle

在我的FragmentActivity我使用了几个片段。当配置改变时(旋转时),系统会破坏并重新创建每个片段 我尝试使用这个重新创建的片段

mFragment = getSupportFragmentManager().findFragmentById(R.id.fragment_frame);

并将其置于新布局

getSupportFragmentManager().beginTransaction()
    .replace(R.id.fragment_frame, mFragment )       
    .commit();

但遇到奇怪的行为:丢失了几个碎片。它们不会更多地显示在屏幕上。在他们的位置是空的。
虽然日志显示片段重新创建正常,但进一步显示片段再次被破坏,再次创建和销毁。

我为节目问题建立了更清晰,没有外壳的测试项目 以及可证明的结果(没有足够的声誉来插入图片
Activity started picture
Activity rotated picture

A,B,C,D是fragments
正如您在配置更改后所看到的,一些片段丢失(B,D)

告诉我我做错了什么

这里是帮助的代码(编辑:将代码推送到gitHub以便更容易尝试)

https:// github.com/nailgilaziev/TestFragmentsRetain

抱歉链接

旋转设备

后记录cat
MainActivity: onPause Activity
MainActivity: onStop Activity
MainActivity: onDestroy Activity
A: onDestroyview
A: onDestroy
B: onDestroyview
B: onDestroy
C: onDestroyview
C: onDestroy
D: onDestroyview
D: onDestroy
MainActivity: onCreate Activity
A: onCreate
B: onCreate
C: onCreate
D: onCreate
MainActivity: replaced
MainActivity: onStart Activity
A: onCreateView
B: onCreateView
C: onCreateView
D: onCreateView

<--before this point all fine and then strange behavior began
for the lost fragments(B,D) are performed unnecessary calls-->

B: onDestroyview
B: onDestroy
D: onDestroyview
D: onDestroy
D: onCreate
D: onCreateView
MainActivity: onResume Activity

1 个答案:

答案 0 :(得分:7)

通过分解问题,使得有两个片段而不是四个片段,当方向发生变化时,您会看到onCreateView在同一个片段上多次被调用。这表明同一片段被添加/创建不止一次。

基本上,当方向发生变化时,您的片段会自动重新附加,因此每次调用FragmentTransaction时都无需执行onCreate(Bundle)

你应该在onCreate(Bundle)做什么而不是......

  1. Null检查传递到savedInstanceState的{​​{1}} Bundle。 - 如果发生方向更改,则会再次调用onCreate(Bundle)onCreate(Bundle)捆绑包将变为非空savedInstanceState FragmentActivity会在重新创建数据之前将其保存在onSaveInstanceState(Bundle)中。

  2. 如果savedInstanceState为空,请创建您的片段并通过FragmentTransaction附加它们。否则,什么都不做。

  3. 总之,您修改后的代码应该类似于以下内容......

    FragmentManager fm = getSupportFragmentManager();
    if(savedInstanceState == null) {
        fm.beginTransaction()
                .replace(R.id.a, new A())
                .replace(R.id.b, new B())
                .replace(R.id.c, new C())
                .replace(R.id.d, new D())
                .commit();
    }
    else {
        a = fm.findFragmentById(R.id.a);
        b = fm.findFragmentById(R.id.b);
        c = fm.findFragmentById(R.id.c);
        d = fm.findFragmentById(R.id.d);
    }
    

    另外,请注意,savedInstanceState onCreate(Bundle)方法中的Fragment捆绑包将始终为空,除非您在onSaveInstanceState(Bundle)中保存了某些内容{1}},所以在重新创建saveInstanceState时,Fragment不会假设FragmentActivity也是非空的,就像{{1}}一样。< / p>