Navigation 3 es una biblioteca de navegación diseñada desde cero para Jetpack Compose. En esta guía, se explica cómo implementar Navigation 3 en aplicaciones para Wear OS.
Conceptos básicos
NavKey: Es un identificador serializable y con seguridad de tipos para un destino (pantalla) en tu app.NavBackStack: Es una lista mutable de instancias deNavKeyque representan el historial de navegación. Puedes enviar y mostrar elementos directamente desde esta lista.rememberNavBackStack: Elemento componible que crea y conserva la pila de actividades en los cambios de configuración y el cierre del proceso.NavDisplay: Es el componente principal de la IU que observa la pila de actividades y renderiza la pantalla activa.EntryProvider: Es un DSL de asignación que vincula unNavKeya su IU de@Composablereal.SwipeDismissableSceneStrategy: Es la estrategia específica para Wear que une tus pantallas en un gesto de deslizar para descartar y controla las animaciones de atrás integradas.
Paso 1: Agrega dependencias
Agrega las dependencias necesarias de Navigation 3, Wear Compose y Serialization a tu proyecto.
Groovy
dependencies { // Core Navigation 3 APIs implementation "androidx.navigation3:navigation3-runtime:1.2.0-alpha02" implementation "androidx.navigation3:navigation3-ui:1.2.0-alpha02" // Wear OS specific Navigation 3 integration implementation "androidx.wear.compose:compose-navigation3:1.6.1" // Kotlinx Serialization for type-safe routing implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.10.0" }
Kotlin
dependencies { // Core Navigation 3 APIs implementation("androidx.navigation3:navigation3-runtime:1.2.0-alpha02") implementation("androidx.navigation3:navigation3-ui:1.2.0-alpha02") // Wear OS specific Navigation 3 integration implementation("androidx.wear.compose:compose-navigation3:1.6.1") // Kotlinx Serialization for type-safe routing implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.10.0") }
Paso 2: Define los destinos (NavKeys)
Las pantallas se definen como objetos serializables o clases de datos con escritura segura que implementan la interfaz NavKey.
@Serializable sealed interface Screen : NavKey { @Serializable data object Home : Screen @Serializable data class Details(val itemId: String) : Screen }
Paso 3: Configura NavDisplay y la pila de actividades
En la raíz de tu aplicación, inicializa la pila de actividades y la estrategia de escena de Wear OS, y, luego, conéctalas a NavDisplay.
// 1. Create the persistent back stack starting at the Home screen val backStack = rememberNavBackStack(Screen.Home) // 2. Initialize the Wear OS swipe-to-dismiss strategy val strategy = rememberSwipeDismissableSceneStrategy<NavKey>() // 3. Render the NavDisplay NavDisplay( backStack = backStack, sceneStrategies = listOf(strategy), entryProvider = entryProvider { // 4. Map keys to Composables entry<Screen.Home> { HomeScreen( onNavigateToDetails = { id -> backStack.add(Screen.Details(id)) } ) } entry<Screen.Details> { key -> DetailsScreen( itemId = key.itemId, onBack = { backStack.removeAt(backStack.lastIndex) } ) } } )
Paso 4: Realiza acciones de navegación
Dado que la pila de actividades secundarias es solo un MutableList personalizado, la navegación es increíblemente sencilla. Realizas operaciones directamente en la instancia de backStack:
- Navegar hacia adelante:
backStack.add(Screen.Details("123")) - Volver:
backStack.removeLast()obackStack.removeLastOrNull() - Borrar y restablecer:
backStack.clear(); backStack.add(Screen.Home)(o usa operaciones de lista para reemplazar la pila).
Paso 5: (Opcional) Define el alcance de los ViewModels para los destinos
De forma predeterminada, los ViewModel se limitan al Activity. Navigation 3 proporciona un artefacto específico (lifecycle-viewmodel-navigation3) para definir de forma segura el alcance de un ViewModel en un NavEntry en la pila de actividades. Cuando el destino se quita de la pila de actividades, se borra el ViewModel.
Agrega la dependencia:
implementation("androidx.lifecycle:lifecycle-viewmodel-navigation3:...")Agrega el decorador de almacén de ViewModel al
entryDecoratorsde tuNavDisplay. También debes incluir de forma explícitaSaveableStateHolderNavEntryDecoratorcuando proporciones decoradores personalizados para conservar el estado derememberSaveablede Compose:NavDisplay( backStack = backStack, sceneStrategies = listOf(strategy), entryDecorators = listOf( rememberSaveableStateHolderNavEntryDecorator(), rememberViewModelStoreNavEntryDecorator() ), entryProvider = entryProvider { entry<Screen.Home> { // Any viewModel() requested here will be scoped to this NavEntry val viewModel: HomeViewModel = viewModel() } } )