That seems promising… Tell me more!

First and foremost, we need to add all the required dependencies. Also, it’s worth mentioning that to use the Navigation Component the Android Studio 3.2 Canary 14 is required.

We will also be using Safeargs — a Navigation Component plugin created to address data exchange between transitions in a type-safe manner.

Navigation graph

This component handles navigation as a graph, where each node represents a screen. These nodes are called destinations and are bounded by each other through actions. The set of destinations and actions compose the navigation graph.

Let’s start by the creating of our navigation graph. So, on your res directory go to New > Android resource file and select Navigation from the resource type list. On the newly created navigation directory, we can start writing our navigation graph.

So, we created our navigation graph but we aren’t hosting it anywhere. A typical use case would be to host it on your root resource.

android:name: Attribute that flags the fragment as a NavHost — A container for the navigation graph that allows destinations to be swapped as the user navigates through the app.

app:navGraph: Connects the NavHostFragment to the navigation graph resource.

app:defaultNavHost: When set to true, NavHostFragment is capable of intercepting the system’s back button presses.

Now you should be able to hop to the design editor of your navigation graph resource and see which resource holds your NavFragmentHost.

Add destinations to your navigation graph

Let’s start simple and add two nodes to our graph — A and B.

From the snippet above, it is worth mentioning the app:startDestination which defines the entry point of the navigation graph. In this case means, fragment A is the first destination of navigation stack.

Connecting destinations

Now that we have two nodes on our graph, we can start defining our navigation flow. This is done through actions. I already talked about these, remember? Actions are the Android Navigation Component equivalent to a graph edge, defined to describe the intent to navigate between destinations.

Trigger navigation

So we have established the connection with a destination, the next move is to actually 🔥 that transition, right? Now, each NavHost has a controller — NavController — that is capable of swapping destinations with one of these two methods:

navigate(): Pushes the specified action destination to the stack.

Pushes the specified action destination to the stack. navigateUp(): Pops to the top destination on the stack. On this case, this method would trigger an app exit since fragment A is the last on the stack.

This wouldn’t be complete without a sweet transition, right? And the icing on the 🍰 is how easy it is to attach it to our action:

app:enterAnim: Defines the animation for fragment B while transitioning to the top of the stack.

app:popEnterAnim: Animation transition for fragment A when populating the top of the stack.

app:exitAnim: Defines the animation of fragment A transitioning to the bottom of the stack.

app:popExitAnim: Animation transition of fragment B leaving the stack.

Despite XML being my go-to, transitions can also be defined programmatically by using an instance of the NavOptions.Builder:

That was easy, right? Let’s see how did it turned out! 🚀

Nested graphs

Let’s imagine that on our hypothetical app, there is a screen flow that is only accessible for premium users. Nested graphs come in handy when dealing with these type of situations, providing the capability to encapsulate destinations. The following b_graph example displayed below encapsulates destinations C and D allowing outside destinations to only trigger actions to the B graph entry point.

Pass data between destinations

Let’s hop again to our hypothetical app and suppose we now want to pass a specific flag from one destination to another 💭… You would probably use Bundle and, to be fair, it would be alright. Despite that, Navigation Component introduced Safe args — a type-safe mechanism to access arguments defined for destinations and actions. It’s useful to prevent the developer from sending a random bundle or accessing it with a wrong key.

First, we need to define the type of argument that we will be sending.

On origin fragment’s side, we need to access the action between the two destinations and attach the desired argument. Safe args generates a Directions class for each one of your destinations, enabling access to its actions and respective arguments.

To retrieve the information, there is also a generated class that has the defined arguments as variables.

Pretty simple, right? 😎