Как сохранить стэк фрагментов приложения на Android при смене ориентации?

Как сохранить стэк фрагментов? У меня приложение построено на архитектуре SingleActivity, то есть, у меня одно MainActivity и много фрагментов. Я хочу что бы приложение при смене ориентации полностью восстанавливало свое состояние вплоть до стэка фрагментов.Что бы можно было при нажатии кнопки назад, перейти в предыдущий фрагмент. Например в приложении ВКонтакте так и сделано. При смене ориентации приложение запускается с того экрана при котором было произведено изменение ориентации. Но при этом, если нажать на кнопку назад вы попадете в предыдущий экран. Я использую MVVM, я понимаю, что можно работать с LiveData и определять какой экран надо запустить при смене ориентации, это не проблема. Но как восстановить стэк фрагментов? Что бы можно было вернуться в предыдущий фрагмент, даже после смены ориентации. Если какие нибудь кейсы или статьи где описано как правильно восстановить приложение после смены ориентации , неважно на Kotlin или Java.


Ответы (2 шт):

Автор решения: Sergei Buvaka

Сохранить сам стек у вас скорее всего не получится т.к. все что живёт внутри активити умирает. Но вы можете заново открыть все фрагменты в том же порядке при воссоздании активити.

Можно создать свой стек в котором будут лежать теги фрагментов (enum или строковые константы). Каждый раз при добавлении фрагмента вы в этот стек кладете тэг. Если вы извлекаете фрагмент, соответственно извлекается и тэг. При повороте экрана вы через вашу ViewModel передаёте этот стек и пот нему заново все восстанавливаете.

Конечно для такой задачи лучше вообще подумать о том, чтоб создать какой-то навигационный компонент, в котором вся эта логика будет обрабатываться. Чтоб активити ничего не знала о тегах и прочей кухне.

Возможно стоит посмотреть в сторону Google Navigation Component или Cicerone от Яндекса. Эти фреймворки рассчитаны на навигацию и вполне возможно, что ребята там уже решили живу проблему.

Вот эта статья должна помочь в вашей проблеме.

→ Ссылка
Автор решения: Yurii Petrov

После прочтения этой статьи, я понял, что надо сохранять не стэк фрагментов а менеджер фрагментов. Андроид автоматически сохраняет менеджер фрагментов при смене ориентации, если установить флаг retainInstance = true в методе onStop().

 override fun onStop() {
        super.onStop()
        retainInstance = true
    }

. Дальше вам надо в главном Activity проверить

if (savedInstanceState==null){
            supportFragmentManager.beginTransaction()
                .replace(R.id.container, Fragment1()).commit()
        }

И все, при смене ориентации вы попадете на тот же фрагмент на котором произошло изменение. И самое главное вы полностью восстановите стэк фрагментов.

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

Что бы все проверить, накидал быстренько приложение из трех фрагментов, все отлично работает, стэк восстанавливается.

→ Ссылка