Android Navigation Components: Passing data between destinations

Android Navigation Components: Passing data between destinations

This is the third article of series Android Navigation components. In the previous articles we looked at Introduction to Android Navigation Componets and Actions in a navigation graph. In this article we will look at passing data between destinations and how to pass data with type-safety using safe args plugin.

Navigation components allow you to attach data to a navigation operation by defining arguments for a destination. For example, pass a user Id to a when the user successfully logins in order to show the correct profile.

You should pass only the minimal amount of data between destinations. For example, you should pass a user id to retrieve the User object rather than passing the object itself, as the total space for all saved states is limited on Android. If you need to pass large amounts of data, consider using a ViewModel as described in Share data between fragments. Android docs .

Defining Destination Arguments

  • Select a destination, e.g. MainFragment, in the navigation graph.

  • Open the attributes window.

  • Click + sign beside arguments attribute to add arguments.

arg.png

A window dialog appears as shown below.

arg_w.PNG

name is the name of the argument that you want to pass, for example name to pass name of the user.

Type. Select the data type of data being passed from the drop down list. By selecting <infered type> you let the navigation library determine the type based on the value passed. If you select custom parcerable, a dialog appears so that you can select the corresponding class.

Array, if checked indicates that the data being passed is an array of the selected data type. Arrays are always nullable.

Default value allows you to define a default value of data being sent.

Passing data between destinations using Bundle

  • Create an object of Bundle class
  • Use navigate() method to pass the bundle to the destination as shown below. navigate() takes two arguments: action id and bundle being used to pass data.

However passing data using Bundle has drawbacks. Suppose the developer on the other end expects an integer but you sent a string? What if you rename the argument from id to userId? The argument will be null on the recipient's end and may throw an exception.

Safe args plugin generate simple object and builder classes for type safe navigation and accessing of associated arguments.

Using safe args plugin to pass data with type safety

If you are not using Gradle you cannot use safe args plugin. Use Bundle as explained above.

Setting up safe args plugin

Include the following classpath in your top level build.gradle file:

buildscript {
    repositories {
        google()
    }
    dependencies {
        def nav_version = "2.1.0"
        classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version"
    }
}

You must also apply either of the two plugins.

To generate Java language code suitable for Java or mixed Java and Kotlin modules, add this line to your app or module's build.gradle file:

apply plugin: "androidx.navigation.safeargs"

To generate Kotlin code suitable for Kotlin-only modules add:

apply plugin: "androidx.navigation.safeargs.kotlin"

When the project builds, the generated code contains the following classes that provide methods to read and write arguments in a safe way.

  • A class is created for each destination. The name of the class is the name of the originating destination, appended the word 'Directions', for example LoginFragmentDirections. The generated class has a method for each action defined in the originating destination.

  • For each action that is used to pass arguments , an inner class is generated whose name is based on the name of the action. For example, action called action_loginFragment_to_MainFragment the inner class is called ActionLoginFragmentToMainFragment.

  • A class is created for the receiving destination. The class is called the name of the receiving destination appended with word 'Args'. For example the receiving destination is called MainFragment and the generated class is MainFragmentArgs This class has fromBundle() method that is used to retrieve the arguments.

The following code example shows how to set and pass arguments from one destination to another.

navigate() no longer takes action id but the action object.

One the receiving destination we will fromBundle() method to retrieve the arguments.

Now you can pass data between destinations with type safety.

Resources; Android Docs

Github project

Other articles in the series Android Navigation Componets

I hope you look forward to the upcoming articles in this series.