Navigation 3

Navigation 3 ist eine Navigationsbibliothek, die von Grund auf für Jetpack Compose entwickelt wurde. In diesem Leitfaden wird beschrieben, wie Sie Navigation 3 in Wear OS-Anwendungen implementieren.

Wichtige Konzepte

  • NavKey: Eine typsichere, serialisierbare Kennung für ein Ziel (einen Bildschirm) in Ihrer App.
  • NavBackStack: Eine veränderliche Liste von NavKey-Instanzen, die den Navigationsverlauf darstellen. Sie können Elemente direkt in diese Liste einfügen und daraus entfernen.
  • rememberNavBackStack: Eine zusammensetzbare Funktion, die den Backstack bei Konfigurationsänderungen und Prozessbeendigung erstellt und beibehält.
  • NavDisplay: Die zentrale UI-Komponente, die den Back Stack beobachtet und den aktiven Bildschirm rendert.
  • EntryProvider: Eine Mapping-DSL, die eine NavKey mit der zugehörigen @Composable-Benutzeroberfläche verknüpft.
  • SwipeDismissableSceneStrategy: Die Wear-spezifische Strategie, die Ihre Bildschirme in eine Wisch-zum-Schließen-Geste einbettet und integrierte Rückwärtsanimationen verarbeitet.

Schritt 1: Abhängigkeiten hinzufügen

Fügen Sie Ihrem Projekt die erforderlichen Navigation 3-, Wear Compose- und Serialisierungsabhängigkeiten hinzu.

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

Schritt 2: Ziele definieren (NavKey)

Bildschirme werden als stark typisierte, serialisierbare Objekte oder Datenklassen definiert, die die NavKey-Schnittstelle implementieren.

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

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

Schritt 3: NavDisplay und den Backstack einrichten

Initialisieren Sie im Stammverzeichnis Ihrer Anwendung den Backstack und die Wear OS-Szenenstrategie und fügen Sie sie dann in NavDisplay ein.

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

Schritt 4: Navigationsaktionen ausführen

Da der Backstack nur eine angepasste MutableList ist, ist die Navigation sehr einfach. Sie führen Vorgänge direkt für die backStack-Instanz aus:

  • Vorwärts navigieren: backStack.add(Screen.Details("123"))
  • Zurück: backStack.removeLast() oder backStack.removeLastOrNull()
  • Löschen und zurücksetzen: backStack.clear(); backStack.add(Screen.Home) (oder verwenden Sie Listenoperationen, um den Stapel zu ersetzen).

Schritt 5 (optional): ViewModels auf Ziele beschränken

Standardmäßig sind ViewModel auf den Activity beschränkt. Navigation 3 bietet ein bestimmtes Artefakt (lifecycle-viewmodel-navigation3), um einen ViewModel sicher auf einen NavEntry im Backstack zu beschränken. Wenn das Ziel aus dem Backstack entfernt wird, wird das ViewModel gelöscht.

  1. Fügen Sie die Abhängigkeit hinzu:

    implementation("androidx.lifecycle:lifecycle-viewmodel-navigation3:...")
    
  2. Fügen Sie den ViewModel-Speicher-Decorator dem entryDecorators Ihres NavDisplay hinzu. Außerdem müssen Sie SaveableStateHolderNavEntryDecorator explizit einfügen, wenn Sie benutzerdefinierte Dekoratoren angeben, um den Compose-Status rememberSaveable beizubehalten:

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