DEV Community

myougaTheAxo
myougaTheAxo

Posted on

Type-Safe Navigation Complete Guide — Kotlin Serialization/Safe Args/Compose

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")
}
Enter fullscreen mode Exit fullscreen mode

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()
)
Enter fullscreen mode Exit fullscreen mode

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
            )
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

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() }
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

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")
Enter fullscreen mode Exit fullscreen mode

Summary

Feature Implementation
Route definition @Serializable data class
Navigation navController.navigate(Route())
Get arguments backStackEntry.toRoute<T>()
Nesting navigation<Graph>()
DeepLink navDeepLink<T>()
  • @Serializable routes 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 templatesGumroad

Top comments (0)