Navigation 3

Navigation 3 est une bibliothèque de navigation conçue de A à Z pour Jetpack Compose. Ce guide explique comment implémenter Navigation 3 dans les applications Wear OS.

Concepts fondamentaux

  • NavKey: identifiant sérialisable et de type sécurisé pour une destination (écran) dans votre application.
  • NavBackStack: liste mutable d'instances NavKey représentant l'historique de navigation. Vous pouvez ajouter et supprimer des éléments directement dans cette liste.
  • rememberNavBackStack: composable qui crée et conserve la pile "Retour" en cas de changement de configuration et d'arrêt du processus.
  • NavDisplay: composant d'UI principal qui observe la pile "Retour" et affiche l'écran actif.
  • EntryProvider: DSL de mappage qui associe un NavKey à son UI @Composable réelle.
  • SwipeDismissableSceneStrategy: stratégie spécifique à Wear qui encapsule vos écrans dans un geste de balayage pour fermer et gère les animations de retour intégrées.

Étape 1 : ajoutez des dépendances

Ajoutez les dépendances requises pour Navigation 3, Wear Compose et la sérialisation à votre projet.

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")
}

Étape 2 : définissez les destinations (NavKeys)

Les écrans sont définis comme des objets ou des classes de données sérialisables et fortement typés qui implémentent l'NavKey interface.

@Serializable
sealed interface Screen : NavKey {
    @Serializable
    data object Home : Screen

    @Serializable
    data class Details(val itemId: String) : Screen
}

Étape 3 : configurez NavDisplay et la pile "Retour"

À la racine de votre application, initialisez la pile "Retour" et la stratégie de scène Wear OS, puis connectez-les à 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) }
            )
        }
    }
)

Étape 4 : effectuez des actions de navigation

Comme la pile "Retour" n'est qu'une MutableList personnalisée, la navigation est incroyablement simple. Vous effectuez des opérations directement sur l'instance backStack :

  • Naviguer vers l'avant : backStack.add(Screen.Details("123"))
  • Naviguer vers l'arrière : backStack.removeLast() ou backStack.removeLastOrNull()
  • Effacer et réinitialiser : backStack.clear(); backStack.add(Screen.Home) (ou utilisez des opérations de liste pour remplacer la pile).

Étape 5 (facultatif) : limitez la portée des ViewModels aux destinations

Par défaut, les ViewModels sont limités au Activity. Navigation 3 fournit un artefact spécifique (lifecycle-viewmodel-navigation3) pour limiter en toute sécurité la portée d'un ViewModel à un NavEntry dans la pile "Retour". Lorsque la destination est supprimée de la pile "Retour", le ViewModel est effacé.

  1. Ajoutez la dépendance :

    implementation("androidx.lifecycle:lifecycle-viewmodel-navigation3:...")
    
  2. Ajoutez le décorateur de magasin ViewModel aux NavDisplay's entryDecorators. Vous devez également inclure explicitement le SaveableStateHolderNavEntryDecorator lorsque vous fournissez des décorateurs personnalisés pour conserver l'état rememberSaveable de 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()
            }
        }
    )