Pass Arguments to Destinations : Jetpack Compose Navigation

Pass Arguments to Destinations : Jetpack Compose Navigation

Introduction:

In Jetpack Compose, you can navigate between different screens using the NavController class from the Navigation component. Passing arguments to the Destination will be like adding Query param or Path to a URL.

To pass arguments to the destination screen, you need to add argument placeholders to the route.

For example, let’s say you have a screen called DetailScreen that displays details of a user, and you want to pass the ID of the user as an argument when navigating to this screen. You can define the route for DetailScreen as "detail/{uId}", where uId is the placeholder for the ID of the user.

Receiving end:

@Composable
fun MyNavHost() {
    val navController = rememberNavController()

    NavHost(
        navController = navController,
        startDestination = "home"
    ) {
        composable("detail/{uId}") { navBackStackEntry ->
            /* Extracting the id from the route */
            val uId = navBackStackEntry.arguments?.getString("uId")
            /* We check if it's not null */
            uId?.let { id->
                DetailScreen(uId = id)
            }
        }
        /* ... */
    }
}

Receiving Object:

Remember, you can only pass a string value to your Destination. But, if you have a data class and want to pass it to your composable then a possible solution is to convert your object to a string using any convertor.

composable("detail/{user}") { navBackStackEntry ->
    // Creating gson object
    val gson: Gson = GsonBuilder().create()
    /* Extracting the user object json from the route */
    val userJson = navBackStackEntry.arguments?.getString("user")
    // Convert json string to the User data class object
    val userObject = gson.fromJson(userJson, User::class.java)
    DetailScreen(user = userObject)
}

Multiple args:

If you want to pass multiple arguments then you can define a route with multiple placeholders separated by slashes (“/”). For example:

composable("detail/{name}/{id}") { backStackEntry ->
    // Extracting the arguments from the route
    val name= backStackEntry.arguments?.getString("name")
    val id= backStackEntry.arguments?.getString("id")

    // Check if arguments are not null and render the screen
    if (name!= null && id!= null) {
        DetailScreen(name, id)
    }
}

Optional args:

If in some cases, you don’t want to have any argument. Then, you can also define it as an optional argument. But, to define an optional argument...

  • We have to use query parameter syntax ("?argName={argName}")

  • We must set a defaultValue, or have nullability = true.

composable(
    route = "detail?uId={uId}",
    arguments = listOf(
        navArgument("uId") {
            defaultValue = 0
            type = NavType.IntType
        }
    )
) { navBackStackEntry ->
    /* Extracting the id from the route */
    val uId = navBackStackEntry.arguments?.getInt("uId")
    /* We check if is null */
    uId?.let {
        DetailScreen(uId = it)
    }
}

And if you want to add more arguments add & between arguments, "?argName1={argName1}&argName2={argName2}"

NOTE: Your passed string/JSON string value should not contain a “/” or your app will crash due to an unexpected path/route.

Sending end:

@Composable
fun HomeScreen(navController: NavController) {
    Button(
        onClick = {
            /* Replacing {uId} with 1 */
            navController.navigate(
                "detail/{uId}" //Just modify your route accordingly
                    .replace(
                        oldValue = "{uId}",
                        newValue = "1"
                    )
            )
        }
    ) {
        Text(text = "Navigate to Detail with id 1")
    }
}

Passing Object:

@Composable
fun HomeScreen(navController: NavController) {
    val userObj = User()
    Button(
        onClick = {   
            val gson: Gson = GsonBuilder().create()            
            val userJson = gson.toJson(userObj)
            /* Replacing {user} with userJson */
            navController.navigate(
                "detail/{user}" //Just modify your route accordingly
                    .replace(
                        oldValue = "{user}",
                        newValue = userJson
                    )
            )
        }
    ) {
        Text(text = "Navigate to Detail with userJson")
    }
}

Conclusion:

This can look a little complex to pass args using Navigation in Jetpack compose, but once you know the basics you’re more ready to expand its usage. It’s no different than passing args to a URL.

I hope you found this helpful. If yes, then do FOLLOW ‘Sagar Malhotra’ for more Android-related content.

#androidWithSagar #android #androiddevelopment #development #compose #kotlin