Скрытые фрагменты backstack, повторно отображаемые при изменении конфигурации - программирование
Подтвердить что ты не робот

Скрытые фрагменты backstack, повторно отображаемые при изменении конфигурации

Я создаю одно действие - несколько фрагментов. Я добавляю в стопку после каждой транзакции. После пары скрытия и отображения фрагментов, а затем я вращаю телефон, все фрагменты, добавленные в контейнер, были восстановлены, и каждый фрагмент находится поверх другого.

В чем может быть проблема? Почему моя активность показывает фрагменты, которые я ранее скрывал?

Я собираюсь скрыть все ранее скрытые, теперь показанные фрагменты, но есть ли более "грациозный" способ сделать это?

4b9b3361

Ответ 1

Используйте setRetainInstance(true) для каждого фрагмента, и ваша проблема исчезнет.
Предупреждение: установка этого значения в true изменит жизненный цикл фрагментов.
Хотя setRetainInstance(true) устраняет проблему, могут быть случаи, когда вы не хотите ее использовать. Чтобы исправить это, настройте логический атрибут на фрагменте и восстановите видимость:

private boolean mVisible = true;
@Override
public void onCreate(Bundle _savedInstanceState) {
    super.onCreate(_savedInstanceState);
    if (_savedInstanceState!=null) {
        mVisible = _savedInstanceState.getBoolean("mVisible");
    }
    if (!mVisible) {
        getFragmentManager().beginTransaction().hide(this).commit();
    }
    // Hey! no setRetainInstance(true) used here.
}
@Override
public void onHiddenChanged(boolean _hidden) {
    super.onHiddenChanged(_hidden);
    mVisible = !_hidden;
}
@Override
public void onSaveInstanceState(Bundle _outState) {
    super.onSaveInstanceState(_outState);
    if (_outState!=null) {
        _outState.putBoolean("mVisible", mVisible);
    }
}

После изменения конфигурации (например, ориентации экрана) экземпляр будет уничтожен, но пакет будет сохранен и введен в новый экземпляр фрагмента.

Ответ 2

У меня была та же проблема. вы должны проверить исходный код в функции onCreateView() вашей деятельности.

public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
    setContentView(R.layout.activity_main);

    if(savedInstanceState == null){//for the first time

        FragmentManager fragmentManager = getFragmentManager();
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

        FragmentExample fragment = new FragmentExample();
        fragmentTransaction.add(R.id.layout_main, fragment);
        fragmentTransaction.commit();

    }else{//savedInstanceState != null
        //for configuration change or Activity UI is destroyed by OS to get memory 
        //no need to add Fragment to container view R.id.layout_main again
        //because FragmentManager supported add the existed Fragment to R.id.layout_main if R.id.layout_main is existed.
        //here is one different between Fragment and View

    }
}

activity_main.xml:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/layout_main">

Ответ 3

Возможно, вы захотите использовать функцию replace(), а не скрывать и показывать. У меня была такая же проблема, когда я начал использовать Fragments, и использование функции replace действительно помогло лучше управлять Fragments. Вот краткий пример:

fragmentManager.replace(R.id.fragmentContainer, desiredFragment, DESIRED_FRAGMENT_TAG)                                   
               .addToBackStack(null)
               .commit();