Navigation with Architecture Components

Android JetPack

Android Jetpack was announced this week at Google IO 2018 and it is something you should definitely direct your attention towards. In an effort to save developers time, the only resource we have a finite amount of, the Android team has prioritized making it easier to get started building great apps with a collection of libraries that streamline your development flow. The libraries cover four key areas of application development:

  • Foundation – AppCompat, Android KTX, Mutlidex & Testing
  • Architecture – Data Binding, Lifecycles, LiveData, Navigation, Paging, Room, ViewModel & WorkManager
  • Behavior – Download manager, Media & playback, Notifications, Permissions, Sharing & Slices
  • UI – Animations & transitions, Auto, Emoji, Fragment, Layout, Palette, TV & Wear OS by Google

As you can see there are a vast number of important topics bundled into this set of libraries to improve developers lives. Additional information can be found at the developer site.

Fragments Again?

This year at IO the android team presented a lot of talks about all the new features that have been developed under the Jetpack umbrella and even more specifically architecture components. With the release of Navigation in architecture components, Google is once again advocating for the use of Fragments within your apps. And, get this they are pushing for single Activity apps if possible having Fragments do the bulk of heavy lifting leaving only things such as top-level navigation and app chrome for the Activity to handle.

Google spent a lot of time digging into Fragments and listened to developers feedback to solve their biggest pain points through these new architecture components. Today we are going to look at one of the new offerings in architecture components, Navigation.

Getting started

Prerequisite – understanding of Android application development and the Kotlin programming language.

All the source code is available on GitHub.

Head over to the Android Studio download site to get the Android Studio 3.2 Preview to get started using Jetpack. Once installed, create a project that includes Kotlin support and adds an Activity via the new Activity & Fragment + ViewModel option.

Okay, that should have created 3 things:

  • MainActivity
  • MainFragment
  • MainViewModel

Next, open up the app/build.gradle file and add the additional dependencies:

Now we should be all set up. If there is an issue with the Kotlin standard library change:

to

MainViewModel

Let’s start with the source of our data for the list of produce products we will display in our sample app. Remove any code from the generated sample class and replace with the following:

As you can see, we are using the new ViewModel architecture component in our MainViewModel but since we are looking into Navigation, I will cover ViewModel in more detail in another post. Next, let us take a look at the MainFragment.

MainFragment

The MainFragment is the home screen of our app hosted within a single Activity.  It will show a list of produce products to the user and listen for items being tapped from the DataAdapter class. When onClick(item: String) gets called we will use the new Navigation architecture component to show the DetailFragment.

In MainFragment we want to do 4 things:

  1. Initialize our MainViewModel
  2. Setup our RecyclerView
  3. Initialize our Adapter
  4. Implement DataAdapter.Listener

The following code shows just this:

As you can see, in the onClick(item: String) method something interesting is happening. We see no FragmentTransaction but when we run the app tap on an item in the RecyclerView we see our DetailFragment loads with no issue. So what exactly is happening here?

Google added a new way to navigate using fragments without the developer ever needing to deal with FragmentTransactions again. Through the static NavHostFragment.findNavControllerMethod(this) call we obtain a NavController from the new NavHostFragment class, more on this shortly. Once we have our NavController we can call navigate() with either and id from our actions, again more on this in a minute, or passing id with a Bundle. So what is this NavHostFragment?

MainActivity

Before answering this let’s first look at the layout file.

Inside our main_activity.xml, you will notice there is a static fragment placed below the Toolbar within the ConstraintLayout. The fragment has a few things we have not seen before:

NavHostFragment is a new class that helps orchestrate the navigation among fragments, but let us look closer at the other 2 new methods.

  1. app:navGraph is a new attribute that points a file in a res/navigation folder, which contains some XML to describe what the NavHostFragment should do when certain NavActions are performed.
  2. app:defaultNavHost allows us to specify this fragment as the default navigation host allowing it to stick on the top of the stack for this NavController.

So what exactly is this nav_graph.xml file?

The navigation graph is a new XML configuration file for setting up a navigation host and it’s NavController using the new navigation editor in Android Studio 3.2. The following XML sets the MainFragment as the starting point and attaches an action with an animation to the destination of the action, the DetailFragment.

Let’s now look back at the MainActivity code and finish up by explaining the power of the Navigation library.

MainActivity

Inside the MainActivity we want to do 2 things:

  1. Set the toolbar as the supportActionBar and add support for back navigation via the NavHostFragment’s NavController
  2. Override onSupportNavigateUp()

In the example, the ActionBar gets linked to the NavHostFragment’s NavController and then the Activity overrides onSupportNavigateUp() to handle back navigation through the same controller. Wow! That was so easy now we have a single Activity app with a list and a DetailFragment. The NavHostFragment manages the loading of the MainFragment and DetailFragment when the respective NavActions are taken via the view elements of our app and the MainActivity is merely a shell for the up navigation and common chrome.

If you found this post helpful please like or share on social networks. Please leave a comment if you find any mistakes in the snippets or consult the github code for a full implementation.