Safe Args and Deep Links
Safe Args
Safe Args generates type-safe code for argument passing. Add the Gradle plugin and define arguments in the navigation graph XML (or programmatically).
With Gradle plugin applied, arguments are accessed directly:
composable(
route = "order/{orderId}",
arguments = listOf(
navArgument("orderId") {
type = NavType.StringType
nullable = false
}
)
) { backStackEntry ->
val orderId = backStackEntry.arguments?.getString("orderId") ?: return@composable
OrderScreen(orderId = orderId)
}
Arguments and Default Values
navArgument("page") {
type = NavType.IntType
defaultValue = 1
}
Deep Links
Deep links allow navigating to a screen from outside the app (notification, link, another app):
composable(
route = "order/{orderId}",
deepLinks = listOf(
navDeepLink {
uriPattern = "myapp://orders/{orderId}"
}
)
) { backStackEntry ->
val orderId = backStackEntry.arguments?.getString("orderId")
OrderScreen(orderId = orderId!!)
}
Register the intent filter in AndroidManifest.xml:
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="myapp" android:host="orders" />
</intent-filter>
Nested Navigation
For feature modules with their own navigation graph:
NavHost(navController, startDestination = "home") {
composable("home") { HomeScreen() }
navigation(startDestination = "orderList", route = "orders") {
composable("orderList") { OrderListScreen() }
composable("orderDetail/{id}") { OrderDetailScreen() }
}
}
Nested graphs keep feature-level navigation contained while sharing the same navController.
Quiz
1. What is the purpose of NavHost in Jetpack Compose Navigation?
2. How do you pass an argument to a composable destination?
3. What does a deep link allow you to do?
4. What is the benefit of nested navigation graphs?
Flashcards
Question
What is the difference between NavController and NavHost?
Click to reveal answer
Answer
NavController manages navigation state and back stack. NavHost renders the composable for the current route. NavController drives NavHost.
Question
How do you extract a route argument in Compose Navigation?
Click to reveal answer
Answer
From backStackEntry.arguments — getString, getInt, getBoolean, etc. Use navArgument to define the type in the route definition.
Question
What is the purpose of deep links in Navigation Component?
Click to reveal answer
Answer
Allow navigating to a specific screen from an external URI (notification, link, another app) without going through the app's normal navigation flow.
Question
When should you use nested navigation graphs?
Click to reveal answer
Answer
When a feature has its own set of screens that share a common prefix route. It encapsulates feature navigation while reusing the parent NavController.
Revision Notes
Key Takeaways
- 1. NavHost renders the composable for the current route; NavController manages navigation state
- 2. Arguments are passed through the route string and extracted from backStackEntry.arguments
- 3. Deep links let external URIs navigate directly to a specific screen
- 4. Nested navigation graphs encapsulate feature-level routes under a common prefix
- 5. Use launchSingleTop and popUpTo to prevent duplicate destinations in the back stack
Interview Tips
- • Explain how Navigation Component replaces manual FragmentTransaction management
- • Demonstrate passing type-safe arguments between screens
- • Discuss deep link setup including intent-filter registration in the manifest
- • Know when to use nested navigation vs flat navigation structure
Cheat Sheet
Navigation Component Cheat Sheet
Core APIs:
rememberNavController()— creates the navigation controllerNavHost(navController, startDestination)— renders destinationsnavController.navigate("route")— navigate to a destinationnavController.popBackStack()— go back
Arguments:
- Route:
"order/{orderId}" - Define:
navArgument("orderId") { type = NavType.StringType } - Extract:
backStackEntry.arguments?.getString("orderId") - Default:
defaultValue = ...
Deep Links:
navDeepLink { uriPattern = "myapp://path" }- Register intent-filter in AndroidManifest.xml
- Supports both implicit and explicit deep links
Nested Navigation:
navigation(startDestination = "list", route = "feature") { ... }- Groups destinations under a common route
- Shares parent NavController
Back Stack:
navController.popBackStack()— pop last destinationnavController.navigate(route) { launchSingleTop = true }— avoid duplicatespopUpTo("route") { inclusive = true }— clear back stack