The Navigation Architecture Component Tutorial: Getting Started

In this tutorial, you’ll learn how to use the Navigation Architecture Component, which simplifies the implementation of navigation in Android apps. By Ivan Kušt.

4.7 (31) · 1 Review

Download materials
Save for later
Share
You are currently viewing page 3 of 3 of this article. Click here to view the first page.

Common Destinations

To reuse actions, you can declare them outside of any destination tags. Such actions are called global actions.

You'll now make showing author details a global action.

Open nav_graph.xml. Move the @+id/actionShowAuthor action from the @+id/workDetailsFragment destination to instead be a direct child of the navigation tag. Now open BookDetailsFragment and replace

// TODO implement navigation to author details

with the following:

findNavController().navigate(
  R.id.actionShowAuthor,
  AuthorDetailsViewModel.createArguments(it)
)

Add the missing import statements:

import androidx.navigation.fragment.findNavController
import com.raywenderlich.android.bookmanstreasure.ui.authordetails.AuthorDetailsViewModel

Build and run your app. Now, you can open author details from both the Work details and Book edition details screens.

Deep Links

Deep links are URLs that link to a specific screen or content of your app. Your next task is to create a deep link to the Favorites screen.

Open nav_graph.xml file. Look for the fragment tags with the @+id/favoritesFragment ID, and paste this between its tags:

<deepLink app:uri="bookmanstreasure://home/favorites" />

The Navigation architecture component will associate the provided URI with the FavoritesFragment. Open AndroidManifest.xml and add the following between the sole activity tags:

<nav-graph android:value="@navigation/nav_graph" />

Add the code to handle deep links at the end of the onCreate() method in MainActivity:

findNavController(this, R.id.navHostFragment).onHandleDeepLink(intent)

And, finally, add the following implementation of the onNewIntent() method to MainActivity:

override fun onNewIntent(intent: Intent?) {
  super.onNewIntent(intent)
  findNavController(this, R.id.navHostFragment).onHandleDeepLink(intent)
}

Make sure to also add the import statement:

import android.content.Intent

Rebuild the app and open the AndroidManifest.xml file. Click on the Merged Manifest tab at the bottom of the editor. You'll notice that the Navigation architecture component has been added a few items:

Generated manifest

To test deep links, you'll create a new Run configuration for the app.

Under the Run configurations dropdown, select Edit configurations... option.

Edit run configurations

Click on the + button in the top-left corner and select Android app from the list. This will create a new empty Run configuration for Android app.

New run configuration details

Set the following properties for the new configuration:

  • Under Name, enter Deep link test.
  • Under Module, select app.
  • Under Launch options select URL
  • Under URL, enter bookmanstreasure://home/favorites.

Now, click on Apply and then OK.

Select the new configuration from Run configurations dropdown and run it.

Select deep link run config

The app should open the Favorites screen.

App opened to Favorites

Nested graphs

To enhance readability and reusability, one navigation graph can be embedded into another. Create a new navigation graph named book_nav_graph.xml - use the same steps you used as when creating nav_graph.xml.

Replace the auto-generated content for the navigation tag with this:

<navigation xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:app="http://schemas.android.com/apk/res-auto"
  xmlns:tools="http://schemas.android.com/tools"
  android:id="@+id/bookDetailsGraph"
  app:startDestination="@id/workDetailsFragment">

</navigation>

There are two things to note:

  • workDetailsFragment is set as the start destination.
  • The ID of the nested graph has been set to bookDetailsGraph.

Now, open nav_graph.xml and move the following actions and destinations to book_nav_graph:

  • actionShowAuthor
  • workDetailsFragment
  • bookDetailsFragment
  • authorDetails

In nav_graph.xml and add the following between the navigation tags:

<include app:graph="@navigation/book_nav_graph" />

Now, open BookSearchFragment and find:

findNavController().navigate(
  R.id.actionBookDetails,
  WorkDetailsViewModel.createArguments(it)
)

Replace it with:

findNavController().navigate(
  R.id.bookDetailsGraph,
  WorkDetailsViewModel.createArguments(it)
)

Note the ID change — you're now pointing to the nested graph. Do the same for FavoritesFragment, then build and run to make sure everything still works!

Conditional Navigation

The last remaining task is to open the Favorites screen if any books have been favorited.

Open nav_graph.xml and add a new destination for LauncherFragment:

<fragment
  android:id="@+id/launcherFragment"
  android:name="com.raywenderlich.android.bookmanstreasure.ui.launcher.LauncherFragment"
  android:label="Blank"
  tools:layout="@layout/fragment_book_details">
  <action
    android:id="@+id/actionBookSearch"
    app:destination="@id/bookSearchFragment" />
  <action
    android:id="@+id/actionFavorites"
    app:destination="@id/favoritesFragment" />
</fragment>

The XML should feel familiar – it's a fragment destination with two actions.

Update the startDestination attribute of the navigation tag to be the following:

app:startDestination="@+id/launcherFragment"

Next, open the LauncherFragment and find:

//TODO implement navigating to Search or Favorites

Replace it with the following:

val destination = if (it.hasFavorites()) {
  R.id.actionFavorites
} else {
  R.id.actionBookSearch
}

findNavController().navigate(
    destination,
    null,
    NavOptions.Builder().setPopUpTo(
        R.id.launcherFragment,
        true
    ).build()
)

Add the following imports:

import androidx.navigation.fragment.findNavController
import androidx.navigation.NavOptions

This will check if there are any favorites and show the appropriate screen. Note the third argument passed to the navigate() function. It specifies navigation options. In this case, it clears the backstack to prevent the user from navigating back to the LauncherFragment.

Note: For a list of all the options available, check the NavOptions.Builder official documentation.

Now, build an run the app. Search for a book, tap on one of the results and add a favorite by tapping on the ❤︎ icon on the top-right.

Adding a favorite

Exit the app, then launch it again. You should land on the Favorites screen.

Where to Go From Here?

You can download the final project using the Download materials button at the top or bottom of the tutorial.

Now you know how to use the Navigation architecture component! Even though it is still in beta, it eases development quite a bit.

A great place to find more information is the official documentation from Google. Also be sure to check out our screencast on the topic.

If you have any questions or tips for others on using the Navigation architecture component, please join in on the forum discussion below!