Фрагмент не разрушен при вращении

У меня есть фрагмент, который добавляется программно. Однако я обнаружил, что после вращения создается новый фрагмент, но старый фрагмент все еще жив (хотя и не отображается). Я предположил, что фрагменты уничтожаются вместе с активностью при вращении, но здесь это не так. Что может привести к тому, что мой фрагмент будет сохранен/не уничтожен? Обратите внимание:

  • Я не устанавливаю setRetainInstance.
  • Фрагмент не добавляется в действие onCreate (добавляется позже при нажатии кнопки)
  • Я вижу, что onDestroy вызывается для Activity после ротации.
  • Хотя фрагмент добавлен, он закрывает кнопку добавления и увольняется только после выполнения "удаления".

Код, создающий фрагмент:

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

UPDATE: Я не могу подтвердить, была ли эта проблема, но фрагмент регистрируется как приемник LocalBroadcast в onCreate. Он незарегистрирован для трансляций в onDestroy, но кажется, что либо регистрация LocalBroadcast препятствовала вызову onDestroy, либо onDestroy не вызывался при ротации. Теперь я отменил регистрацию в onStop, и это, похоже, решило проблему.

Ответ 1

Когда действие перезапускается из-за изменения ориентации, Android Framework воссоздает и автоматически добавляет фрагмент. Вероятно, вы добавите фрагмент в onCreate вашего Activity. Это, когда вы добавляете дополнительный фрагмент после изменения ориентации.

Вам нужно проверить, добавлен ли фрагмент:

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

При каждом нажатии кнопки, которая добавляет фрагмент, будет добавлен новый фрагмент. Если ваш контейнер является FrameLayout, вы, вероятно, его не увидите. Попробуйте заменить фрагменты:

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

Метод setRetainInstance(true) имеет другую цель. Если вы включите его, экземпляр Fragment не будет уничтожен при изменении ориентации (но его виды будут уничтожены). Это означает, что вы можете хранить данные в переменных-членах Fragment, и эти данные по-прежнему будут доступны после изменения ориентации.

При настройке setRetainInstance(true) жизненный цикл фрагмента несколько отличается. То есть onCreate() и onDestroy() не вызываются (потому что это событие не происходит)

Ответ 2

Почему не можете заменить существующий фрагмент новым фрагментом, который вы хотите загрузить.

попробуйте, это может вам помочь.

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

Ответ 3

Ваш фрагмент, вероятно, сохранит объект Bundle перед активностью onDestroy(). Попробуйте обработать удаление фрагментов в onSaveInstanceState():

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

Или вы можете просто сделать Bundle null в onCreate():

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

Ответ 4

У меня была эта проблема, и я решил ее просто Заменить эту строку

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

Для

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

Enjoy

Ответ 5

Вам просто нужно добавить 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();
    }
}