3

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

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

并将其放入新布局

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

但遇到奇怪的行为:丢失了几个片段。它们不会更多地显示在屏幕上。取而代之的是空的。
虽然日志显示片段被重新创建很好,但进一步显示片段被再次销毁,再次创建并再次销毁。

我构建测试项目以更清晰地显示问题并且没有外壳。
以及可证明的结果(没有足够的声誉插入图片
Activity 启动图片
Activity 旋转图片

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

告诉我我做错了什么

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

https:// github.com/nailgilaziev/TestFragmentsRetain

p/s 抱歉链接

在我旋转设备后在这里记录猫

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
4

1 回答 1

7

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

基本上,当方向改变时,您的 Fragments 将自动重新附加,因此无需FragmentTransaction每次onCreate(Bundle)调用​​时都执行 a。

你应该做的onCreate(Bundle)是......

  1. 空检查savedInstanceState传入的 Bundle onCreate(Bundle)。-- 如果方向发生变化,onCreate(Bundle)将再次调用并且savedInstanceStateBundle 将变为non-null。在重新创建数据之前FragmentActivity保存数据。onSaveInstanceState(Bundle)

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

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

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);
}

另外,请注意,a 方法中的savedInstanceStateBundle将始终为空,除非您将某些内容保存到其中的情况。onCreate(Bundle)FragmentonSaveInstanceState(Bundle)saveInstanceStateFragmentFragmentActivity

于 2013-05-26T20:18:17.130 回答