What You'll Learn
Type-safe Navigation (Kotlin Serialization integration, @Serializable routes, type-safe arguments, nesting support) explained.
Setup
// build.gradle.kts
plugins {
kotlin("plugin.serialization")
}
dependencies {
implementation("androidx.navigation:navigation-compose:2.8.5")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.3")
}
Route Definition
@Serializable
object Home
@Serializable
object Settings
@Serializable
data class UserDetail(val userId: String)
@Serializable
data class ProductDetail(
val productId: Int,
val category: String = "all"
)
@Serializable
data class SearchResult(
val query: String,
val page: Int = 1,
val filters: List<String> = emptyList()
)
NavHost Setup
@Composable
fun AppNavigation() {
val navController = rememberNavController()
NavHost(navController, startDestination = Home) {
composable<Home> {
HomeScreen(
onUserClick = { userId -> navController.navigate(UserDetail(userId)) },
onSettingsClick = { navController.navigate(Settings) },
onProductClick = { id, cat -> navController.navigate(ProductDetail(id, cat)) }
)
}
composable<Settings> {
SettingsScreen(onBack = { navController.popBackStack() })
}
composable<UserDetail> { backStackEntry ->
val userDetail = backStackEntry.toRoute<UserDetail>()
UserDetailScreen(userId = userDetail.userId)
}
composable<ProductDetail> { backStackEntry ->
val product = backStackEntry.toRoute<ProductDetail>()
ProductDetailScreen(
productId = product.productId,
category = product.category
)
}
}
}
Nested Navigation
@Serializable object AuthGraph
@Serializable object Login
@Serializable object Register
@Serializable object MainGraph
@Serializable object Feed
@Serializable object Profile
@Composable
fun AppNavigation() {
val navController = rememberNavController()
NavHost(navController, startDestination = AuthGraph) {
navigation<AuthGraph>(startDestination = Login) {
composable<Login> {
LoginScreen(
onLoginSuccess = {
navController.navigate(MainGraph) {
popUpTo(AuthGraph) { inclusive = true }
}
},
onRegister = { navController.navigate(Register) }
)
}
composable<Register> { RegisterScreen() }
}
navigation<MainGraph>(startDestination = Feed) {
composable<Feed> { FeedScreen() }
composable<Profile> { ProfileScreen() }
}
}
}
DeepLink Support
composable<ProductDetail>(
deepLinks = listOf(
navDeepLink<ProductDetail>(basePath = "https://example.com/product")
)
) { backStackEntry ->
val product = backStackEntry.toRoute<ProductDetail>()
ProductDetailScreen(product.productId, product.category)
}
// https://example.com/product/123?category=electronics → ProductDetail(123, "electronics")
Summary
| Feature | Implementation |
|---|---|
| Route definition | @Serializable data class |
| Navigation | navController.navigate(Route()) |
| Get arguments | backStackEntry.toRoute<T>() |
| Nesting | navigation<Graph>() |
| DeepLink | navDeepLink<T>() |
-
@Serializableroutes are compile-time type-safe - No string-based route definition needed
- Arguments type-checked at compile time
- Available in Navigation 2.8+
Ready-Made Android App Templates
8 production-ready Android app templates with Jetpack Compose, MVVM, Hilt, and Material 3.
Browse templates → Gumroad
Top comments (0)