Navigation Component
π§ Navigation Component
πΊοΈ The Nav Graph
A nav graph is an XML resource listing every destination (usually a Fragment) and the actions connecting them:
Android Studio's Navigation Editor shows this graph visually, as boxes connected by arrows β dragging a connection between two Fragments writes the corresponding <action> XML automatically, which is normally faster than hand-editing this file directly.
π NavHostFragment β Where the Graph Lives
An Activity hosts the whole graph through a single special Fragment, replacing the plain FrameLayout container from Chapter 6:
app:navGraph wires this container to the nav graph resource; app:defaultNavHost="true" makes the system Back button correctly step backward through the nav graph's own back stack, rather than falling through to the Activity's default Back behavior.
β‘οΈ Navigating Between Destinations
findNavController() locates the NavController managing the graph this Fragment lives in, and navigate(...) follows the specified action β no manual FragmentManager.beginTransaction() call needed anymore. The library also automatically pushes this navigation onto a back stack, so the system Back button (and an app's own explicit "up" button) work correctly without any extra code.
π SafeArgs β Type-Safe Argument Passing
Chapter 4's Intent.putExtra / getStringExtra pattern is stringly-typed and easy to typo. SafeArgs (a Gradle plugin, added to build.gradle.kts) generates typed argument classes directly from arguments declared in the nav graph:
Intent Extras vs SafeArgs
| Intent.putExtra (Chapter 4) | SafeArgs | |
|---|---|---|
| Key | Raw string, must match exactly | Named parameter β checked by the compiler |
| Type | Chosen getter (getStringExtra, etc.) β can mismatch | Declared once in the nav graph, generated correctly everywhere |
| Missing value | Runtime null / crash | Compile error if a required argument isn't provided |
args: DetailsFragmentArgs by navArgs() reuses Kotlin Intermediate Chapter 4's property delegation directly β navArgs() is itself a delegate provided by the Navigation library, following the exact same by mechanism as lazy or a custom delegate.
π Back Stack Management
Every navigate() call pushes the new destination onto the graph's back stack automatically. An action can also specify popUpTo to remove destinations from the stack as part of navigating β useful for flows like "after login, don't let Back return to the login screen":
popUpTo="@id/loginFragment" with popUpToInclusive="true" removes loginFragment itself (and anything above it) from the back stack while navigating to homeFragment β pressing Back from the home screen then skips login entirely, exiting the app instead, exactly the behavior a real login flow needs.
π Deep Links
A deep link lets an external source (a notification, a web link, another app) open the app directly at a specific destination, rather than always starting from the launcher Activity:
Tapping a myapp://details/Philip link anywhere on the device (a notification, a browser link with the app's scheme registered) launches the app directly into DetailsFragment, with userName automatically populated as a SafeArgs argument β no manual Intent parsing required.
Navigation Component vs Web Routing
| React Router / Next.js | Navigation Component | |
|---|---|---|
| Route definitions | <Route path="/details/:id"> or file-based routes | nav_graph.xml destinations + actions |
| Typed params | useParams() (often untyped without extra work) | SafeArgs-generated Args classes |
| Programmatic navigation | navigate("/details/5") | findNavController().navigate(action) |
| Deep linking | Just... a URL, inherently | Explicit <deepLink> declarations needed |
π» Coding Challenges
Challenge 1: Convert Chapter 6's Fragments to a Nav Graph
Take WelcomeFragment and DetailsFragment from Chapter 6, create a nav_graph.xml with both as destinations and an action between them, replace the FrameLayout container with a NavHostFragment, and replace the manual FragmentManager.replace() call with findNavController().navigate().
Goal: Directly experience the FragmentManager-to-NavGraph migration.
Challenge 2: Pass an Argument with SafeArgs
Add the SafeArgs Gradle plugin, declare a String argument named "message" on detailsFragment in the nav graph, send it from WelcomeFragment using the generated Directions class, and display it in DetailsFragment using navArgs().
Goal: Practice the full SafeArgs round trip, replacing the Intent-extras pattern from Chapter 4 with its type-safe nav-graph equivalent.
Challenge 3: popUpTo Behavior
Add a third destination, homeFragment, and an action from detailsFragment to homeFragment that uses popUpTo/popUpToInclusive to clear both welcomeFragment and detailsFragment off the back stack. In a comment, describe what pressing Back from homeFragment would do as a result.
Goal: Practice configuring back stack behavior declaratively via an action's attributes.
Navigation Component is genuinely how most real, multi-screen Android apps handle moving between screens today β the manual FragmentManager approach from Chapter 6 is worth understanding as the foundation, but this declarative graph-based approach is what actual production code reaches for. The final chapter covers resources and styling in more depth, rounding out Course 1's foundation.
π― What's Next
Next chapter β the final chapter of Course 1: Resources & Styling β string/color/dimen resources in depth, themes, and dark mode basics.