Navigation in Compose – NavHost mit Argumenten
Von der Liste zum Detail und mit einer ID zurück: Navigation Compose macht das mit NavHost, Routen und typisierten Argumenten. So richtest du den Grundfluss sauber ein.
Sobald deine App mehr als einen Screen hat, brauchst du einen Navigations-Graphen. In Jetpack Compose übernimmt das die Bibliothek Navigation Compose: ein NavController merkt sich den Back-Stack, ein NavHost beschreibt die möglichen Ziele als Routen.
Dependency in build.gradle.kts:
implementation("androidx.navigation:navigation-compose:2.8.0")Der Graph
import androidx.navigation.compose.*
import androidx.navigation.NavType
import androidx.navigation.navArgument
@Composable
fun AppNav() {
val navController = rememberNavController()
NavHost(navController = navController, startDestination = "list") {
composable("list") {
TaskList(onOpen = { id -> navController.navigate("detail/$id") })
}
composable(
route = "detail/{id}",
arguments = listOf(navArgument("id") { type = NavType.LongType })
) { backStackEntry ->
val id = backStackEntry.arguments?.getLong("id") ?: 0L
TaskDetail(id = id, onBack = { navController.popBackStack() })
}
}
}Was hier passiert
rememberNavController()erzeugt den Controller und überlebt Recompositions.- Jede
composable(route)ist ein Ziel. Die Route"detail/{id}"enthält einen Platzhalter. navArgument+NavType.LongTypetypisiert das Argument – du liest es alsLongstatt als String zu jonglieren.navigate("detail/42")springt zum Detail,popBackStack()geht zurück.
Ein wichtiger Grundsatz
Reiche dem Ziel-Composable nur die ID herein, nicht das ganze Objekt. Der Detail-Screen lädt seine Daten selbst (z. B. über sein ViewModel) anhand der ID. So bleibt die Navigation schlank, übersteht Prozess-Neustarts und du vermeidest, komplexe Objekte durch den Back-Stack zu schleusen.
Wenn du eine mehrseitige Android-App in Kotlin & Compose brauchst, melde dich bei mir.
Quellen
Du brauchst mehr als ein Snippet?
Ich entwickle Android-Apps in Kotlin und moderne Websites für Selbstständige und kleine Unternehmen — von der ersten Idee bis zum Release.
Projekt anfragen →Verwandte Snippets
Room-Migrationen – das Schema ändern, ohne Nutzerdaten zu verlieren
Eine neue Spalte in der Entity, und beim nächsten Start ist der Spielstand weg – weil fallbackToDestructiveMigration die Datenbank einfach löscht. So machst du es richtig, inklusive Test.
stateIn und shareIn – aus einem kalten Flow wird geteilter Zustand
Jeder Sammler eines kalten Flows startet die Arbeit neu – zwei Beobachter, zwei Datenbankabfragen. stateIn und shareIn machen daraus einen Strom, den sich alle teilen, samt aktuellem Wert und Abschalten bei Inaktivität.
viewModelScope – Coroutinen, die mit dem Bildschirm verschwinden
Eine Coroutine, die nach dem Schließen des Bildschirms weiterläuft, schreibt in ein ViewModel, das niemand mehr sieht – und hält im schlimmsten Fall die ganze Activity im Speicher. viewModelScope beendet sie automatisch.