Updated date:

Working With the Androidx Navigation Api Component

Davinder Singh is a Polymath. He loves reading, learning and writing technical cookbooks about new technologies.

Android JetPack Hero

Android JetPack Hero

What You Will Learn

  • You will learn what AndroidX is.
  • You will learn what the Navigation Component is.
  • You will learn how to add Navigation into the AndroidX project.
  • You will learn what NavEditor, NavController, and NavGraph are.

Lastly, you will learn passing data between transitions from one fragment to another with SafeArgs API which comes bundled with the Navigation Component.

What Is Navigation API?

Navigation API is a component of AndroidX (Android JetPack). It helps in managing and implementing transitions whether from activity-to-activity, fragment-to-fragment, or activity-to-fragment. It is inspired by flutter's navigation controller. All you have to do is describe the routes that your application goes through in the form of a navigation graph and Navigation API takes care of the rest. Navigation API also contains methods for data passing in between fragments and listeners to handle fragment transitions.

Features of Navigation API

  • You don't have to request FragmentManager ever again for transitioning from one fragment to another.
  • You only need to describe the routes, i.e., transition; Which can be described in XML in WYSIWY fashion with navigation graph editor tool.
  • You don't need to write factory methods for passing data from one start to destination screen. Navigation API provides SafeArgs API where you can describe the type of data, its name, and default type.
  • Transition animation can be inscribed in the navigation graph itself.
  • Fragments and routes implemented with navigation API can be easily deep linked with the help of deep linking API present in Navigation API.
  • Navigation API also provides back button listener in NavHostFragment meaning you no longer have to iterate fragment back stack every time to determine which fragment is currently at top etcetera.

Terminologies of Navigation API

  • NavHost is an activity hosting container fragment i.e NavHostFragment content of which is replaced as the user navigates from one screen to another screen.
  • NavController is an object of singleton class which is built during the Gradle building process just like the R class. It provides all the methods to handle navigation as well as argument passing.
  • Destination Start is that screen from which we can navigate to some other destination.
  • Destination is that screen to which we travel from the start. A start can have multiple destinations depending upon the scenarios.
  • Placeholder is an empty container which you can replace with a fragment or an activity later.

Navigation Editor

Navigation editor is part of Android Studio version 3.3. It's a tool integrated in the studio to edit navigation graph in What You See Is What You Get (WYSIWYG) fashion.

Android Studio Navigation Editor

Android Studio Navigation Editor

  1. Destinations is where you will see all the fragments and activities that are present in the navigation graph. It is divided into two sections viz. NavHost and Destinations.
  2. Graph Editor is where you can visually add connections in between fragments. Here you can define the relationship between screens. It is somewhat similar to but not fully featured like XCode's segue editor.
  3. Attribute editor or Inspector is where we can edit all kind of properties regarding transitions. Such as adding arguments list for this transition, transitional animations, and DeepLinks.

Implementing Navigation API

In this article, we will make a simple application using navigation API to have a taste of it. However, we will keep it simple. Our sample application will consist of two fragments and one main activity. The main fragment contains two buttons one button simply navigates to the second fragment while the second button passes date string onto the second fragment.

Step 1: Add Navigation Resource Directory

Create a new Android Studio project with AndroidX (make sure you have the latest version of studio), and under the language tab select Kotlin. After Gradle is done configuring the project add two fragments to the project; One will act as NavHost, and another is destination fragment.

  • Right click on the resources folder (res) and add a new Android Resource Directory. In directory type select navigation and click ok. A new directory named navigation will be added to the resource directory.
  • Right-click the navigation resource directory and add new XML resource directory name this file nav_graph.xml.
  • Double click to open this file. Android Studio will automatically launch navigation editor.
Project with Kotlin and AndroidX

Project with Kotlin and AndroidX

Step 2: Add Fragments in NavEditor

Now that we have nav_graph.xml file opened in navigation editor. Let's add fragments in the navigation editor.

  • Go to top left corner of the menu bar in navigation editor and click on the green plus sign. A submenu will appear containing a list of fragment and activities present in the projects.
  • Select all the screens present in the list (only fragments) and add them to navigation editor's destination bar.
Adding destinations

Adding destinations

Step 3: Add Transitions

Now that we have added fragments to in destinations. We have two tasks left to perform, i.e., selecting a NavHost controller and linking the destinations with start. I am assuming that you have two fragments in the project viz. MainMenu fragment and Second fragment and MainActivity. Add the following code in activity_main.xml layout file.

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">
   <!-- This fragment is loaded by default -->
    <fragment
            <!-- Here we are declaring that this fragment is NavHostFragment -->
            android:name="androidx.navigation.fragment.NavHostFragment"
            android:layout_width="0dp"
            android:layout_height="0dp"
            <!-- NavGraph used by this fragment -->
            app:navGraph="@navigation/nav_graph"
           <!-- This is our application's defaultNavHost -->
            app:defaultNavHost="true"
            android:id="@+id/fragment"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintTop_toTopOf="parent"/>

</androidx.constraintlayout.widget.ConstraintLayout>

Navigate to navigation editor again, see the difference? The previously emptied host section is filled with activity_main.

  • Right-click mainMenu fragment in the destinations and select Destination Start.
  • Click on side of mainMenu circle, and drag the pointer till secondFragment, connecting them both.

Step 4: Add Transition Triggers

Now that we have completed the linking part, only thing left is to add triggers for executing the transitions. Go to mainMenu fragment (having two buttons) add click listener to anyone from them. We will add code inside the clickListener to execute transition. Compile and run the application. Click on that button and see transition happening. If it didn't worked however try commenting your issue below, I will help you out.

//kotlin
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        //btFirst is id of button
        view.btFirst.setOnClickListener {
            //Navigation Controller
            Navigation.findNavController(view)
                .navigate(R.id.secondFragment)
        }
 }

Step 5: Passing Data With NavController

Navigation API as I said earlier also contains data passing API called SafeArgs. You can use this API or send data with the bundle. We will only implement SafeArgs in this article.

  • Goto navigation editor in (previous example) and select secondFragment.
  • Goto inspector on the right-hand side in navigation editor and click on '+' just after Argument list.
  • A new dialog will appear, give default value "Hello World" or whatever you want and Name argument. Leave type to <inferred type>.
Add argument dialog

Add argument dialog

Goto project's top level build.gradle file and add the following dependencies.

buildcript{
    ...
   dependencies {
       //Add this
        classpath "android.arch.navigation:navigation-safe-args-gradle-plugin:1.0.0-alpha11"
    }
}

In module level build.gradle add following dependencies and sync the project.

//Add these line at the top
apply plugin: 'kotlin-android-extensions'

apply plugin: 'androidx.navigation.safeargs'


dependencies {
   //Add this in the dependencies
    implementation 'android.arch.navigation:navigation-fragment:1.0.0-alpha11'
}

Step 6: Passing Data With SafeArgs

In MainMenu fragment where you added two buttons, In second button (the one to which listener hasn't yet assigned). Now add following code to pass along Date string to next screen.

//MainMenuFragment.kt  
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        view.btFirst.setOnClickListener {
            Navigation.findNavController(view)
                .navigate(R.id.secondFragment)
        }

        view.btSecond.setOnClickListener {
            /*
              action describes a transition
              MainMenuDirection is an auto generated class.
              Naming follows as [DestinationStartClass's Name]Directions 
              for example if name of the class is Home then you'll 
              end up with HomeDirections.
           */
            val action = MainMenuDirections.actionMainMenuToSecondFragment()

           action.argument = "Today is " + SimpleDateFormat("dd/mm/yyyy", Locale.getDefault())
                .format(Date())

            Navigation.findNavController(view)
                .navigate(action)
        }
    }

Step 7: Retrieving Data From SafeArgs

In another fragment or destination fragment, We will have to add code to retrieve the argument or data in the second fragment. Every destination fragment contains an argument bundle which is controlled by the NavController. Again a class is auto-generated for destination fragment. If destination fragment name is SecondFragment then the auto-generated class will have the name SecondFragmentArgs. Below is code to retrieve the argument (argument name is ironically argument with string type).

//SecondFragment.kt
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        val args = SecondFragmentArgs.fromBundle(arguments!!)
        view.tvArgs.text = args.argument
}

Conclusion

This was a short introduction to Navigation API. In my next article I will write about room api. Room api is for fast-forwarding the implementation of SQLHandler and persistence database handling. If you ran into errors then try googling the issues or comment it below. Follow and share. Thank you for reading. Source code for final application is present here.

This article is accurate and true to the best of the author’s knowledge. Content is for informational or entertainment purposes only and does not substitute for personal counsel or professional advice in business, financial, legal, or technical matters.

© 2019 Dav Vendator