Navigation Compose ist eine Jetpack-Bibliothek für deklarative Navigation innerhalb von Android-Anwendungen, die auf Jetpack Compose basieren. Anstelle von FragmentManager oder Intent-basierter Navigation bietet Navigation Compose einen einheitlichen Routengraphen, der über NavController und NavHost verwaltet wird. Laut Google I/O (2025) ist Navigation Compose die empfohlene Navigationsmethode für Compose-Anwendungen und wird in mehr als 70% der neuen Projekte verwendet. Die Bibliothek unterstützt die Übergabe typisierter Argumente, Deep Links, Übergangsanimationen und die Integration mit ViewModel über SavedStateHandle.
Wichtige Punkte
Navigation Compose ist eine Bibliothek aus der Jetpack-Suite, die ein Navigationsframework für Compose-Anwendungen bereitstellt. Die Bibliothek basiert auf denselben Prinzipien wie die Navigationskomponente für das View-System, ist jedoch an die deklarative Natur von Compose angepasst: Anstelle von FragmentTransaction werden composable-Funktionen verwendet, und der Navigationsgraph wird über Kotlin DSL erstellt.
Der Hauptunterschied zwischen Navigation Compose und der klassischen Navigation ist das Fehlen von FragmentManager. Jeder Bildschirm ist eine composable-Funktion, die in NavHost gerendert wird, wenn die Route übereinstimmt. Der Back-Stack speichert kein Fragment, sondern einen Datensatz mit Route, Argumenten und Zustand. Dies vereinfacht die Architektur und beseitigt Lebenszykluskonflikte, die für die Fragment-basierte Navigation typisch sind.
Laut Google (2025) ist Navigation Compose von experimentell zu stabil geworden und seit Version 2.8.0 Teil von Jetpack. Die Bibliothek unterstützt Material3, typsichere Navigation (über Kotlin Serialization), verschachtelte Graphen und Modularisierung. Die einzige Einschränkung ist, dass die Bibliothek ohne manuelle Konfiguration keinen Multi-Back-Stack für BottomNavigation unterstützt, obwohl Google daran arbeitet.
Die Architektur von Navigation Compose dreht sich um drei Entitäten: NavController (Stapelverwaltung), NavHost (Graphcontainer) und NavDestination (einzelne Route mit composable). Die Interaktion zwischen ihnen ist deklarativ: Der Entwickler beschreibt Routen und Argumente, und die Bibliothek kümmert sich um Lade-, Erhaltungs- und Wiederherstellungszustände.
NavController ist das zentrale Element von Navigation Compose und verwaltet den Navigationsstapel. Er wird über rememberNavController() erstellt und an NavHost übergeben. NavController speichert den Back-Stack, den aktuellen Einstiegspunkt und unterstützt verzögerte Aktionen (Deeplink nach der Graphinitialisierung).
@Composable
fun AppNavigation() {
val navController = rememberNavController()
NavHost(navController = navController, startDestination = "home") {
composable("home") { HomeScreen(navController) }
composable("profile/{userId}") { backStackEntry ->
ProfileScreen(
userId = backStackEntry.arguments?.getString("userId") ?: ""
)
}
}
}
Wichtigste NavController-Methoden: navigate(route) — zu einer Route navigieren, popBackStack() — zum vorherigen Bildschirm zurückkehren, navigateAndClear(route) — navigieren und den Stapel leeren. NavOptions geben das Verhalten an: launchSingleTop verhindert Duplikate, popUpTo leert den Stapel bis zur angegebenen Route, restoreState stellt den vorherigen Zustand wieder her.
Um von tief verschachtelten composable-Funktionen auf NavController zuzugreifen, verwenden Sie NavHostController über CompositionLocal. LocalNavController wird in ScopedNavController innerhalb von NavHost bereitgestellt. Außerhalb von NavHost (z.B. in BottomNavigation) wird der Controller über Parameter oder ViewModel übergeben.
NavHost ist ein composable-Container, der NavController mit dem Routengraphen verbindet. Jede Route wird über composable(route, arguments, deepLinks) deklariert, wobei route eine Routenzeichenfolge mit optionalen {param}-Platzhaltern ist. Wenn die aktuelle Route übereinstimmt, rendert NavHost den entsprechenden composable-Block.
Der Routengraph wird hierarchisch aufgebaut: Graphen können über navigation() verschachtelt werden, um Routen innerhalb eines Moduls zu gruppieren. Verschachtelte Graphen haben einen eigenen startDestination und werden unter einem gemeinsamen Routenpräfix zusammengefasst. Dies ermöglicht eine modulare Architektur, bei der jedes Feature-Modul seinen eigenen Untergraphen registriert.
NavHost(
navController = navController,
startDestination = "main"
) {
composable("main") { MainScreen(navController) }
navigation(
route = "auth",
startDestination = "auth/login"
) {
composable("auth/login") { LoginScreen(navController) }
composable("auth/register") { RegisterScreen(navController) }
}
}
NavHost verarbeitet automatisch die System-Zurück-Taste (Back Press) über LocalBackDispatcher. In Material3 Scaffold übernimmt es standardmäßig NavController für den korrekten BottomNavigation-Betrieb. NavHost erstellt composable bei Routenänderung neu, bewahrt aber den Zustand über rememberSaveable für Eingabefelder und Scrollen.
Navigation Compose unterstützt die Übergabe typisierter Argumente zwischen Bildschirmen über Routenparameter und NavType. Parameter werden in der Route als {paramName} mit dem Typ angegeben, der durch arguments in composable() angegeben wird. NavType unterstützt String, Int, Long, Float, Boolean, Parcelable und Serializable.
| Argumenttyp | NavType | Routenbeispiel |
|---|---|---|
| String | NavType.StringType | "profile/{name}" |
| Int | NavType.IntType | "item/{id}" |
| Boolean | NavType.BoolType | "settings?enabled={flag}" |
| Parcelable | NavType.ParcelableType | "details/{item}" |
| Float | NavType.FloatType | "map?lat={lat}&lng={lng}" |
Argumente werden aus NavBackStackEntry über arguments?.getType(key) extrahiert. Für obligatorische Parameter verwenden Sie defaultValue, für optionale — nullable. Die Parcelable-Unterstützung funktioniert nur mit Kotlin Parcelize oder der Bibliothek kotlinx.parcelize. Für komplexe Objekte wird empfohlen, eine ID zu übergeben und Daten über ViewModel zu laden, anstatt das gesamte Objekt zu serialisieren.
Seit Navigation 2.8.0 wurde die typsichere Navigation mit Kotlin Serialization eingeführt: Routen werden als Datenklassen und Argumente als Felder definiert. Dies ersetzt String-Routen durch typisierte Objekte und beseitigt Fehler in Routennamen. Für die Migration sind das Kotlin Serialization-Plugin und die Abhängigkeit navigation-compose-typesafe erforderlich.
@Serializable
/* sealed class Route */
sealed class ProfileRoute(val route: String) {
data object Home : ProfileRoute("home")
data class Profile(val userId: String) : ProfileRoute("profile/{userId}")
}
Deep Links sind ein Navigationsmechanismus, der das Öffnen eines bestimmten Anwendungsbildschirms über eine URL oder einen Intent-Filter ermöglicht. In Navigation Compose werden Deep Links über den Parameter deepLinks in composable() konfiguriert und automatisch verarbeitet, wenn die URI mit dem Muster übereinstimmt.
Ein Deep Link wird als UriPattern-Liste angegeben: "https://example.com/profile/{userId}". URI-Parameter werden automatisch auf Routenargumente abgebildet. NavController verarbeitet Deep Links beim Anwendungsstart (über Intent) und während des Betriebs (über implizite Deep Links). Zur Behandlung ausstehender Deep Links verwenden Sie handleDeepLink() in NavController nach der Graphinitialisierung.
Laut Google werden Deep Links empfohlen für: Push-Benachrichtigungen (Firebase Dynamic Links), E-Mail-Verifizierung, Inhaltsfreigabe und übergreifende Navigation aus Web-Links. Für Android 12+ werden Digital Asset Links zur Überprüfung der Deep-Link-Autorität verwendet. AndroidManifest.xml muss einen Intent-Filter mit autoVerify="true" enthalten, um Links ohne Dialog zu öffnen.
composable(
route = "profile/{userId}",
arguments = listOf(navArgument("userId") { type = NavType.StringType }),
deepLinks = listOf(
navDeepLink { uriPattern = "https://example.com/profile/{userId}" }
)
) { backStackEntry ->
ProfileScreen(userId = backStackEntry.arguments?.getString("userId") ?: "")
}
Einschränkungen von Deep Links in Navigation Compose: Die Bibliothek unterstützt keine verzögerten Deep Links — ein Deep Link wird erst verarbeitet, nachdem NavHost den Graphen vollständig erstellt hat. Wenn ein Deep Link vor der Graphinitialisierung eintrifft, muss er über intent?.data verzögert und in LaunchedEffect verarbeitet werden. Für Firebase Dynamic Links verwenden Sie das Firebase Dynamic Links SDK zusammen mit Navigation Compose.
Navigation Compose unterstützt Übergangsanimationen über die Parameter enterTransition, exitTransition, popEnterTransition und popExitTransition in composable(). Animationen werden mit der Compose Animation API implementiert: fadeIn, slideInHorizontally, expandIn und andere. Standardmäßig ist die Animation deaktiviert — Bildschirme werden sofort ersetzt.
Typische Animationsszenarien: slideInHorizontally für Vorwärtsnavigation (Bildschirm gleitet von rechts ein), slideOutHorizontally für Rückkehr (Bildschirm gleitet nach rechts aus). Für BottomNavigation wird häufiger eine Einblendanimation ohne Gleiten verwendet. Animationen werden über NavHost festgelegt und gelten für alle composables, sofern keine individuellen angegeben sind.
NavHost(
navController = navController,
startDestination = "home",
enterTransition = { slideInHorizontally() + fadeIn() },
exitTransition = { slideOutHorizontally() + fadeOut() },
popEnterTransition = { fadeIn() },
popExitTransition = { slideOutHorizontally() + fadeOut() }
) { /* composable */ }
Animationen können für jedes composable einzeln überschrieben werden, indem Animationsparameter direkt in composable() übergeben werden. Wichtig: Animationen sollten nicht mit der System-Zurück-Taste-Animation kollidieren. Für Shared-Element-Übergänge wird die Bibliothek accompanist-navigation-animation oder eine benutzerdefinierte Implementierung über Modifier.graphicsLayer benötigt. Laut Android Developers (2025) verwenden 80% der Produktionsanwendungen horizontale Gleitanimationen für die Standardnavigation.
Häufig gestellte Fragen
Navigation Compose arbeitet ohne Fragment und verwendet composable-Funktionen und Kotlin DSL für den Graphen. Die Navigationskomponente (View) basiert auf FragmentManager und XML-Graphen. Die Compose-Version ist einfacher, schneller und hat keine Fragment-Lebenszyklen. Die Navigationskomponente für View ist nur für Hybridanwendungen geeignet.
Es wird empfohlen, die Objekt-ID zu übergeben und Daten über ViewModel mit SavedStateHandle zu laden. Wenn das Objekt einfach ist, verwenden Sie Parcelable über kotlinx.parcelize. Das direkte Übergeben großer Objekte über Argumente (Bundle) ist auf ~1 MB begrenzt und kann TransactionTooLargeException verursachen.
Ja, über die Funktion navigation(route, startDestination) innerhalb von NavHost. Verschachtelte Graphen haben einen eigenen startDestination und werden unter einem gemeinsamen Routenpräfix zusammengefasst. Dies ermöglicht eine modulare Architektur mit isolierten Graphen für jedes Feature-Modul.
NavController verarbeitet den Zurück-Tastendruck automatisch über BackHandler von Compose. Rufen Sie navController.popBackStack() auf, wenn Zurück gedrückt wird. Für eine benutzerdefinierte Behandlung (Ausstiegsbestätigung) verwenden Sie BackHandler(enabled = condition) { callback } vor dem Aufruf von popBackStack().
Derzeit wird Navigation Compose in Compose Multiplatform nicht unterstützt. Verwenden Sie für den iOS-Teil plattformübergreifender Projekte Voyager oder Decompose. Google arbeitet an der KMP-Unterstützung, aber es gibt keinen Veröffentlichungszeitplan. Für reine Android-Projekte ist Navigation Compose die einzig empfohlene Option.
Zusammenfassung
Wir entwickeln eine mobile Applikation schlüsselfertig
IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.
Lesen Sie auch