В следующих разделах описываются стратегии сохранения вашего стека переходов и сохранения состояния, связанного с записями в вашем стеке переходов.
Сохраните свой стек
Обеспечение сохранения состояния навигации вашего приложения при различных событиях жизненного цикла, включая изменения конфигурации и завершение процесса, критически важно для хорошего пользовательского опыта. В 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
Другой подход к управлению стеком изменений — хранение его в 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. - Добавьте
rememberSaveableStateHolderNavEntryDecorator()в списокentryDecoratorsпри построенииNavDisplay. - Добавьте другие декораторы в ваш
NavDisplay.
NavDisplay( entryDecorators = listOf( // Add the default decorators for managing scenes and saving state rememberSaveableStateHolderNavEntryDecorator(), // Then add the view model store decorator rememberViewModelStoreNavEntryDecorator() ), backStack = backStack, entryProvider = entryProvider { }, )