Routes and Arguments

Defining Routes and Passing Arguments

Until Navigation 2.8.0 (September 2024), a route was a string, shaped like a URL path, with arguments as {placeholders} declared separately. Most existing code still looks like this, so you need to read it:

ui/nav/StringRoutes.kt: the older string-route style (excerpt)Kotlin
  NavHost(nav, startDestination = "catalog") {
    composable("catalog") {
      Column {
        books.take(3).forEach { b ->
          TextButton(onClick = { nav.navigate("book/${b.id}") }) { Text(b.title) }
        }
      }
    }
    composable("book/{id}", arguments = listOf(navArgument("id") { type = NavType.IntType })) {
      val id = it.arguments?.getInt("id")                // untyped: a Bundle lookup by name
      Log.d("BookNestNav", "string route ${it.destination.route}, id=$id")
      Text("Book $id")
    }
  }

Tapping Salt and Saffron logged:

Output of 121
D/BookNestNav: string route book/{id}, id=3

It works, but nothing checks it: a typo in "book/$id" or "id" compiles and fails at run time, and the type is declared in one place and read in another. Pass an ID, never the object: arguments are saved in the back stack's Bundle, and a large one can exceed the 1 MB binder limit. (The line was logged three times, once per composition, a reminder that a composable body is no place for side effects.)