В следующих разделах описываются стратегии сохранения стека переходов и состояния, связанного с записями в стеке переходов.
Сохраните свой стек
Обеспечение сохранения состояния навигации вашего приложения в различных событиях жизненного цикла, включая изменения конфигурации и завершение процесса, имеет решающее значение для хорошего пользовательского опыта. В Navigation 3 вы являетесь владельцем своего стека переходов назад, поэтому нет строгих указаний о том, как его создавать или сохранять. Однако Navigation 3 предлагает удобный метод, который предоставляет вам сохраняемый стек переходов назад: rememberNavBackStack
.
Используйте rememberNavBackStack
Компонуемая функция rememberNavBackStack
предназначена для создания обратного стека, который сохраняется при изменении конфигурации и завершении процесса.
Для корректной работы rememberNavBackStack
каждая клавиша в вашем стеке должна соответствовать определенным требованиям:
- Реализовать интерфейс
NavKey
: каждый ключ в стеке возврата должен реализовывать интерфейсNavKey
. Это действует как интерфейс маркера, который сигнализирует библиотеке о том, что ключ может быть сохранен. - Наличие аннотации
@Serializable
: Помимо реализацииNavKey
, ваши ключевые классы и объекты должны быть отмечены аннотацией@Serializable
.
В следующем фрагменте показана правильная реализация rememberNavBackStack
:
@Serializable data object Home : NavKey @Composable fun NavBackStack() { val backStack = rememberNavBackStack(Home) }
Альтернатива: хранение в ViewModel
Другой подход к управлению вашим back stack заключается в его сохранении в ViewModel
. Для сохранения после смерти процесса при использовании ViewModel
или любого другого пользовательского хранилища вам необходимо:
- Убедитесь, что ваши ключи сериализуемы : как и в случае с
rememberNavBackStack
, ваши навигационные клавиши должны быть сериализуемыми. - Выполняйте сериализацию и десериализацию вручную : вы несете ответственность за ручное сохранение сериализованного представления каждого ключа в постоянном хранилище (например,
SharedPreferences
, базе данных или файле) и его десериализацию из него, когда ваше приложение переходит в фоновый режим или восстанавливается.
Область действия ViewModel
в NavEntry
ViewModels
используются для сохранения состояния, связанного с пользовательским интерфейсом, при изменении конфигурации, например, при поворотах экрана. По умолчанию ViewModels
ограничены ближайшим ViewModelStoreOwner
, который обычно является вашим Activity
или Fragment
.
Однако вам может потребоваться ограничить ViewModel
определенным NavEntry
(т. е. определенным экраном или пунктом назначения) в стеке переходов назад, а не всем Activity
. Это гарантирует, что состояние ViewModel
сохраняется только пока этот конкретный NavEntry
является частью стека переходов назад, и очищается при извлечении NavEntry
.
Библиотека дополнений androidx.lifecycle:lifecycle-viewmodel-navigation3
предоставляет NavEntryDecorator
, который облегчает это. Этот декоратор предоставляет ViewModelStoreOwner
для каждого NavEntry
. Когда вы создаете ViewModel
внутри содержимого NavEntry
(например, используя viewModel()
в Compose), он автоматически ограничивается этим конкретным ключом NavEntry
в стеке переходов. Это означает, что ViewModel
создается при добавлении NavEntry
в стек переходов и очищается при его удалении.
Чтобы использовать NavEntryDecorator
для ограничения области действия ViewModel
до NavEntry
, выполните следующие действия:
- Добавьте зависимость
androidx.lifecycle:lifecycle-viewmodel-navigation3
в файлapp/build.gradle.kts
. - Добавьте
rememberSavedStateNavEntryDecorator()
в списокentryDecorators
при построенииNavDisplay
. - Добавьте другие декораторы в ваш
NavDisplay
.
NavDisplay( entryDecorators = listOf( // Add the default decorators for managing scenes and saving state rememberSceneSetupNavEntryDecorator(), rememberSavedStateNavEntryDecorator(), // Then add the view model store decorator rememberViewModelStoreNavEntryDecorator() ), backStack = backStack, entryProvider = entryProvider { }, )