Навигация 3 – это фундаментальное изменение в том, как Jetpack Compose обрабатывает состояние навигации. Она предлагает значительные архитектурные преимущества по сравнению с Навигацией 2.
Узнайте об изменениях в архитектуре и шагах, необходимых для переноса приложения Wear Compose с Navigation 2 на Navigation 3.
Основные преимущества Navigation 3
- Прямое управление стеком возврата.
NavBackStack– это изменяемый список объектовNavKey, представляющий историю экранов, которые посетил пользователь. Вы управляете им так же, как и любым другим объектом KotlinMutableList(add,removeLast,clear). Вы напрямую работаете со списком, чтобы выполнять действия навигации, например добавлять ключ для перехода вперед или удалять ключ для перехода назад. - Compose-First Design: обратный стек моделируется как стандартное наблюдаемое состояние. Изменение истории навигации работает так же, как обновление любого другого состояния Compose, автоматически вызывая повторную композицию для отображения текущего экрана.
- Безопасность типов по умолчанию. Маршруты на основе строк полностью исключены. Для навигации используются сериализуемые объекты данных и классы данных.
- Отдельные презентации (стратегии сцен). Слой перехода интерфейса (
NavDisplayиSwipeDismissableSceneStrategy) полностью отделен от отслеживания состояния (NavBackStack), что упрощает интеграцию встроенных переходов навигации Wear OS.
Этапы переноса
1. Обновление зависимостей
Удалена старая зависимость androidx.wear.compose:compose-navigation и добавлены новые разделенные зависимости Navigation 3, а также поддержка сериализации Kotlin.
Удалить
implementation("androidx.wear.compose:compose-navigation:...")
Добавить:
implementation("androidx.navigation3:navigation3-runtime:...") // State logic
implementation("androidx.navigation3:navigation3-ui:...") // Display logic
implementation("androidx.wear.compose:compose-navigation3:...") // Wear gestures
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:...") // Requires compiler plugin
2. Как обновить целевые страницы, чтобы реализовать NavKey
В Navigation 2 для маршрутизации могли использоваться строки или универсальные объекты. В Navigation 3 обязательно нужно реализовать интерфейс маркера NavKey и добавить аннотацию @Serializable к каждому объекту экрана.
Зачем это нужно? Чтобы стек возврата можно было сохранить и восстановить после завершения процесса, лежащий в основе navigation3-runtime использует kotlinx-serialization для сериализации состояния.
До (Navigation 2 – универсальные маршруты с безопасностью типов):
sealed class Nav2Screen { data object Landing : Nav2Screen() data object List : Nav2Screen() }
После (Navigation 3 – NavKey + Serializable):
@Serializable sealed interface MigrationScreen : NavKey { @Serializable data object Landing : MigrationScreen @Serializable data object List : MigrationScreen }
3. Заменить логику маршрутизации (NavController на NavBackStack)
Замените NavController на NavBackStack, инициализированный с помощью rememberNavBackStack. Вам также нужно создать экземпляр SwipeDismissableSceneStrategy специально для Wear OS.
До (Навигация 2):
val navController = rememberSwipeDismissableNavController()
После (Навигация 3):
val backStack = rememberNavBackStack(MigrationScreen.Landing as NavKey) val strategy = rememberSwipeDismissableSceneStrategy<NavKey>()
4. Замените NavHost на NavDisplay и entryProvider DSL.
Контейнер NavHost и его внутренний конструктор composable("route") { ... } DSL заменены на NavDisplay и entryProvider {
entry<Key> { ... } } DSL.
До (Навигация 2):
SwipeDismissableNavHost(navController = navController, startDestination = "menu") { composable("menu") { GreetingScreen( onShowList = { navController.navigate("list") } ) } composable("list") { ListScreen() } }
После (Навигация 3):
NavDisplay( backStack = backStack, sceneStrategies = listOf(strategy), entryProvider = entryProvider { entry<MigrationScreen.Landing> { GreetingScreen( onShowList = { backStack.add(MigrationScreen.List) } ) } entry<MigrationScreen.List> { ListScreen() } } )