片段在旋转时没有被破坏

时间:2013-12-05 13:52:01

标签: android android-fragments

我有一个以编程方式添加的片段。然而,我发现在旋转之后,会创建一个新片段,但旧片段仍处于活动状态(虽然没有显示)我假设片段与旋转活动一起被销毁,但这不是这里的情况。什么可能导致我的片段被保留/不被破坏? 请注意:

  1. 我没有设置setRetainInstance。
  2. 片段未添加到活动onCreate(稍后在点按按钮时添加)
  3. 我可以看到在旋转时调用onDestroy
  4. 虽然添加了片段,但它会模糊添加按钮,只有在我执行“删除”时才会被删除。
  5. 创建片段的代码:

    MyFragment fragment = MyFragment();
    FragmentManager fragmentManager = getFragmentManager();
    FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
    fragmentTransaction.add(R.id.content_frame, fragment, "CurrentFragment");
    fragmentTransaction.show(fragment).commit();
    

    删除片段的代码:

    FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
    fragmentTransaction.remove(fragment).commit();
    

    更新: 我无法确认这是否是问题,但片段在onCreate中注册为LocalBroadcast接收器。它在onDestroy中未注册广播,但似乎LocalBroadcast注册阻止调用onDestroy,或者在旋转时没有调用onDestroy。我现在在onStop中取消注册,这似乎解决了这个问题。

5 个答案:

答案 0 :(得分:15)

当由于方向更改而重新启动Activity时,Android Framework会自动为您重新创建并添加Fragment。 您可能会在onCreate的{​​{1}}中添加片段。这是您在方向更改后添加其他片段的位置。

您必须检查是否已添加片段:

Activity

每次添加添加片段的按钮时,都会添加一个新的片段。如果您的容器是FrameLayout,您可能不会看到它。尝试替换碎片:

Fragment f = getFragmentManager().findFragmentById(R.id.content_frame);
if(f == null){
    //Add it, there is no Fragment
}else{
    //It's already there
}

方法fragmentTransaction.replace(R.id.content_frame, fragment, "CurrentFragment"); 有另一个目的。如果启用它,则方向更改时将不会销毁setRetainInstance(true)实例(但其视图将被销毁)。这意味着您可以将数据存储在Fragment的成员变量中,并且这些数据在方向更改后仍然可用。

设置Fragment时片段的生命周期略有不同。即setRetainInstance(true)onCreate()未被调用(因为这些事件不会发生)

答案 1 :(得分:2)

为什么不能用要加载的新片段替换现有片段。

试试这可能对你有帮助。

FragmentNew mFragmentNew = new FragmentNew ();// Which you want to load That Fragment Object 
        getFragmentManager().beginTransaction()
                .replace(R.id.item_detail_container, mFragmentNew)
                .commit();

答案 2 :(得分:2)

你的片段可能在活动onDestroy()之前保存在Bundle对象中。尝试在onSaveInstanceState()中处理删除片段:

@Override
    protected void onSaveInstanceState(Bundle outState) {
        //remove here fragments
        super.onSaveInstanceState(outState);
    }

或者你可以在onCreate()中使Bundle为null:

@Override
    protected void onCreate(Bundle savedInstanceState) {
        savedInstanceState = null;
        super.onCreate(savedInstanceState);
    }

答案 3 :(得分:1)

我遇到了这个问题,我解决了这个问题,只需更换此行

fragmentTransaction.add(R.id.content_frame, fragment, "CurrentFragment");

fragmentTransaction.replace(R.id.content_frame, fragment, "CurrentFragment");

享受

答案 4 :(得分:0)

首次启动时只需添加Fragment一次,就像这样: 以下代码是从http://developer.android.com/reference/android/app/Fragment.html复制的,评论是我的:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);


    // My Comment: only add when launched for the first time, it won't be null on orientation change
    if (savedInstanceState == null) {
        // During initial setup, plug in the details fragment.
        DetailsFragment details = new DetailsFragment();
        details.setArguments(getIntent().getExtras());
        getFragmentManager().beginTransaction().add(android.R.id.content, details).commit();
    }
}