Instruction

The Purpose of Navigation with Arguments

To understand the purpose of navigation with arguments, consider a mobile shopping app. You’re browsing shoes and find a pair you like. Tapping the shoe image takes you to the product details screen. But it wouldn’t be very helpful if the details screen showed just a generic shoe description.

Here’s where navigation arguments come in: — On the shoe browsing screen, you tap the specific shoe you like. — The navigation call includes arguments like the shoe’s ID number or name. — The product details screen receives these arguments and uses them to display the specific details, images, and purchase options for that particular shoe.

Without arguments, the product details screen wouldn’t know which shoe to display, making the navigation clunky and unhelpful. Navigation arguments help share and pass data from one part/screen of the app to another while navigating.

Defining Navigation Arguments

Jetpack Compose navigation provides support for passing arguments between composable destinations of a navigation graph. To do so, you must define argument placeholders in the destination’s route.

For instance, here’s a code snippet defining a destination for product details page with a product ID as an argument:

NavHost(startDestination = "product-list-page") {
  composable("product-details-page/{productId}") { ... }
}

Although by default all arguments are treated as strings, note that you can explicitly specify the type of argument using NamedNavArgument, which you can define using the navArgument() method.

You can pass the list of NamedNavArgument as the arguments parameter of the composable() function that you used to add a composable as a destination in the graph, as shown below:

NavHost(startDestination = "product-list-page") {
  composable(
    "product-details-page/{productId}",
    arguments = listOf(navArgument("productId") { type = NavType.StringType })
  ) { ... }
}

Jetpack Compose supports the following types of navigation arguments: Integer, Float, Long, Boolean, String, and a few others such as Resource references, Parcelable, Serializable, and Enums.

Accessing Navigation Arguments

So far, you’ve learned how to define a navigation argument. Now, it’s time to understand how to extract and access an argument.

You can access navigation arguments from the NavBackStackEntry. The NavController holds a ‘back stack’ that contains the destinations the user visits in the app, and each destination in the stack is a NavBackStackEntry. Like any other stack, the back stack has a ‘last in, first out’ orientation, so the most recent destination is at the stack’s top and the least recent one is at the bottom.

Here’s how you can access the argument using the NavBackStackEntry:

composable("product-details-page/{productId}") { backStackEntry ->
  ProductDetailsScreen(navController, backStackEntry.arguments?.getString("productId"))
}

Passing Navigation Arguments

To pass an argument to the destination, you must add it to the route when calling the navigate() function as follows:

navController.navigate("product-details-page/shoes-1629")

Handling Complex Data When Navigating

It’s strongly recommended not to pass large or complex data as navigation arguments but instead to pass minimum required data, which the destination can use to get access to required large or complex data, ideally using a data layer.

For instance, in the code snippet above, we passed an ID of a product that the ProductDetailsScreen uses to find details of a particular product.

Optional Arguments

Jetpack Compose also supports optional navigation arguments, which differ from required arguments in the following ways: — They’re included using the query parameter syntax — ?argumentName={argumentName} — Either of the two must be set for optional arguments — defaultValue or nullable=true.

Here’s a code snippet showing how to add an optional argument to the composable() function:

composable(
  "product-list-page/saleDiscountEnabled={saleDiscountEnabled}",
  arguments = listOf(navArgument("saleDiscountEnabled") { defaultValue = false })
) { backStackEntry ->
  ProductListScreen(navController, backStackEntry.arguments?.getString("saleDiscountEnabled"))
}

If no value for saleDiscountEnabled is provided, the defaultValuefalse — is used. Otherwise, the argument value provided is used.

Now, it’s time to implement code that uses navigation with arguments.

See forum comments
Download course materials from Github
Previous: Introduction Next: Demo