Navigation In Jetpack Compose

3 min readJun 14, 2023

In this blog we will learn how to perform navigate with Jetpack Compose. You can navigate between composables while taking advantage of the Navigation component’s infrastructure and features.


dependencies {
def nav_version = "2.5.3"


Getting Started

First we need to create and remember NavController. You should create the NavController in the place in your composable hierarchy where all composables that need to reference it have access to it. This follows the principles of state hoisting.

val navController = rememberNavController()

Next, we need an NavHost Composable. Each NavControllermust be associated with a single NavHostcomposable. The NavHost links the NavController with a navigation graph that specifies the composable destinations that you should be able to navigate between. As you navigate between composables, the content of the NavHost is automatically recomposed. Each composable destination in your navigation graph is associated with a route.

NavHost(navController = navController, startDestination = "destination_login") {
composable(route = "destination_login") { Login(/*...*/) }
composable(route = "destination_profile") { Profile(/*...*/) }
composable(route = "destination_list") { List(/*...*/) }

NavHost composable takes navController and startDestination which is inturn a composable. startDestination is the starting point for the nav-graph.

All the different composables are defined within NavHost. Composables need to have unique route to identify them.

Navigation to composables —

To navigate to composable you must use navigate method. navigate takes a single parameter which is route to identify the destination.


If you want to modify the behavior of navigate like add launch modes or pop existing composables from stack it can be done via -

navController.navigate("destination_profile") {
launchSingleTop = true

navController.navigate("destination_profile") {

navController.navigate("destination_profile") {
//inclusive pops including the destination mentioned.
popUpTo("destination_login") { inclusive = true }

Navigation with Arguments —

Navigation compose also supports passing arguments between composable destinations. In order to do this, you need to add argument placeholders to your route.

route = "destination_editItem/id={id}",
arguments = listOf(navArgument(name = "id") {
type = NavType.StringType

Data that is passed to the arguments can be retrieved with help of SavedStateHandle at the destination’s ViewModel.

class EditItemModel(
private val savedStateHandle: SavedStateHandle,
) : ViewModel() {

private val userId: String = savedStateHandle.get<String>("id")

//Perform operations with the id.

If the arguments are optional then add the nullable flag with arguments in route as ?.

route = "destination_addUri?uri={uri}",
arguments = listOf(navArgument(name = "uri") {
nullable = true
type = NavType.StringType

If you want to close a composable and redirect user back to particular screen, it can be done with popBackStack. Onclick of the action button popBackStack with route and the other flags like inclusive and saveState can be passed.

navController.popBackStack(route = "destination_list", inclusive = true)

Deeplinks —

Navigation Compose supports implicit deep links that can be defined as part of the composable() function as well.

composable(route = "destination_feedlist", deepLinks = listOf(navDeepLink { uriPattern = "$uri/id" })) {

deeplinks is a parameter in composable which takes listOf uriPattern with which you can specific URL, action or mime type to associate with composable.

By default, deeplinks are not available outside of the application. An intent-filter would be needed to make it externally available.

This covers the basics of navigation in compose.

That’s all for now. Thanks.

Please feel free to reach out to me on LinkedIn.

If you liked this blog, don’t forget to hit the 👏 .