Navigation (Fragment & Compose) Quiz
UI › Material & Nav
In Navigation Compose with type-safe routes, how do you read the arguments inside a destination's composable?
- backStackEntry.arguments?.getString("id")
- backStackEntry.toRoute<DetailRoute>()
- navController.getArguments<DetailRoute>()
- SafeArgs.fromBundle(backStackEntry)
Answer: backStackEntry.toRoute<DetailRoute>()
toRoute<T>() deserializes the back stack entry into the @Serializable route instance, giving typed access. Raw Bundle getString is the old string-route approach, and SafeArgs is the XML/Fragment generator, not used here.
Which combination prevents a destination from being duplicated on the back stack when re-selecting the same bottom-nav tab?
- Use popUpTo with inclusive = true, without any singleTop
- Use launchSingleTop with popUpTo to the graph start
- Call navigate() twice so the tab refreshes its destination
- Set a deep link on the destination to reuse the same screen
Answer: Use launchSingleTop with popUpTo to the graph start
launchSingleTop reuses the existing top instance instead of pushing a new copy; combined with popUpTo to the graph start it gives the standard duplicate-free bottom-nav behavior.
What does Safe Args generate for XML-based navigation graphs?
- Type-safe Directions and Args classes for checked arguments
- A serialized JSON copy of the nav graph created at runtime
- Composable destination wrappers built specifically for Jetpack Compose
- An AndroidManifest intent-filter added for each destination screen
Answer: Type-safe Directions and Args classes for checked arguments
The Safe Args Gradle plugin generates Directions (for navigating with arguments) and Args (for reading them) classes, replacing untyped Bundle keys with compile-time-checked types.
Which statement best distinguishes an implicit deep link from an explicit deep link?
- Implicit deep links only ever function within nested navigation graphs
- Explicit deep links each require their own intent-filter in the manifest
- Implicit links are URI matches via intent-filter; explicit ones jump right to a destination
- Explicit deep links are unable to reconstruct the navigation back stack at all
Answer: Implicit links are URI matches via intent-filter; explicit ones jump right to a destination
Implicit deep links are URI matches declared via intent-filter/navDeepLink so external sources open the app at a destination, while explicit deep links (e.g. NavDeepLinkBuilder/PendingIntent) navigate in-app directly, typically from notifications.
How should a ViewModel be scoped so two sibling destinations in the same flow can share it?
- Scope it to the Application so it becomes a global singleton.
- Create a separate ViewModel for each destination in the flow.
- Keep the data in a companion object shared across screens.
- Scope it to the navigation graph, like navGraphViewModels.
Answer: Scope it to the navigation graph, like navGraphViewModels.
Graph-scoped ViewModels live as long as the graph is on the back stack, so destinations within that graph share one instance. Application scope leaks state globally and per-destination instances cannot share data.
In Navigation Compose, what is a destination registered inside a NavHost?
- A composable function registered via composable(...)
- An Activity entry declared inside the manifest file
- A Fragment subclass registered in the navigation graph
- A separate XML layout resource under res/layout
Answer: A composable function registered via composable(...)
Navigation Compose destinations are composables registered with composable(route) (or composable<Route> for type-safe routes) inside the NavHost; Fragments and Activities are not the unit of navigation here.
What does popUpTo("home") { inclusive = true } do when navigating?
- Adds 'home' to the back stack again before opening the new screen.
- Removes destinations up to and including 'home' before nav.
- Saves 'home' state so it can be restored after navigating back.
- Turns off the up button on the destination you just opened.
Answer: Removes destinations up to and including 'home' before nav.
popUpTo removes entries up to the named destination, and inclusive = true also removes 'home' itself, so the new destination effectively replaces the popped stack.
In Jetpack Compose, what is the idiomatic way to obtain the NavController that survives recomposition and is handed to a NavHost?
- Construct NavController(context) in the composable body
- Inject it with hiltViewModel()
- val navController = rememberNavController()
- Read it from LocalNavController.current, which Compose always provides
Answer: val navController = rememberNavController()
rememberNavController() creates and remembers a NavHostController across recompositions so the back stack is preserved. There is no built-in CompositionLocal for it, and constructing one each recomposition would discard navigation state.
What is the practical difference between NavController.navigateUp() and NavController.popBackStack()?
- navigateUp() uses Up semantics and can fail at a graph root; popBackStack() always pops the top
- They are just identical aliases for one and the same pop operation
- popBackStack() always finishes the host Activity, whereas navigateUp() never does
- navigateUp() pushes a new destination while popBackStack() just removes one
Answer: navigateUp() uses Up semantics and can fail at a graph root; popBackStack() always pops the top
navigateUp() encodes Up affordance behaviour and may differ at a graph's start destination (for example with synthesized deep-link back stacks), while popBackStack() simply removes the current destination from the stack.
What is required to use type-safe @Serializable routes in Navigation Compose?
- Adding the Safe Args Gradle plugin to the project's build
- Annotating every single route class with @Parcelize
- Declaring each route as a separate entry in AndroidManifest.xml
- Apply the Kotlin serialization plugin and annotate routes with @Serializable
Answer: Apply the Kotlin serialization plugin and annotate routes with @Serializable
Type-safe routes are encoded and decoded with kotlinx.serialization, so the org.jetbrains.kotlin.plugin.serialization plugin must be applied and each route annotated @Serializable. Safe Args is the older XML/Fragment-only generator and is unrelated here.
In a single-activity app, what is the recommended way to return a result from a destination back to the screen that launched it?
- Call startActivityForResult between the two destinations, then handle the callback
- Write it to the previous entry’s SavedStateHandle and observe it in the caller
- Store it in a global variable and read it after popBackStack() returns
- Pass it forward as a navigation argument to the next destination instead
Answer: Write it to the previous entry’s SavedStateHandle and observe it in the caller
Each NavBackStackEntry exposes a SavedStateHandle; the called destination sets a value on previousBackStackEntry's SavedStateHandle and the caller observes it (as LiveData/StateFlow). Navigation arguments only flow forward, not back.
How can a ViewModel read its destination's navigation arguments without them being passed manually through the constructor?
- By calling navController.getBackStackEntry() from inside the ViewModel
- It cannot be done; ViewModels are cut off from navigation arguments entirely
- Through the injected SavedStateHandle, pre-seeded with the arguments
- By reading the host Activity's Intent extras passed at launch time
Answer: Through the injected SavedStateHandle, pre-seeded with the arguments
A ViewModel scoped to a NavBackStackEntry receives a SavedStateHandle pre-populated with that destination's arguments, so it can read them by key (or via toRoute) with no constructor plumbing.
How do you declare a nested navigation graph in the Navigation Compose DSL?
- With a nested navigation(startDestination = ...) { } block in NavHost
- By placing another NavHost inside the first destination’s composable screen
- By adding an android:nestedGraph attribute to the app manifest file
- Nested graphs are only available in XML graphs, not in Navigation Compose
Answer: With a nested navigation(startDestination = ...) { } block in NavHost
In Compose you group destinations into a subgraph using the navigation(...) builder with its own start destination inside the NavHost; this scopes the feature and enables graph-scoped ViewModels. Nested graphs are fully supported in Compose.
Which API lets a Compose bottom bar reactively highlight the tab matching the currently displayed destination?
- Reading navController.currentDestination a single time during composition
- Polling navController.backQueue on a timer
- Calling navController.addOnDestinationChangedListener directly in the composable body without remembering it
- navController.currentBackStackEntryAsState(), comparing its destination's route to each tab
Answer: navController.currentBackStackEntryAsState(), comparing its destination's route to each tab
currentBackStackEntryAsState() returns a State<NavBackStackEntry?> that recomposes on every destination change, so the bar can compare the current route to each item and mark the selected one. A one-time read never updates, and an unremembered listener re-registers on each recomposition.