Safe Args — the Navigation Component’s best friend

Anton Uryvskii
3 min readJan 20, 2021

In this story, you will get to know what Safe Args is, how it simplifies work with NavComp and what is the result of its work including that under the hood.

You are now in the second part of a large story about the Navigation Component in a multi-module project. If you are hearing about Navigation Component for the first time, I recommend that you first read what Navigation Component is. If you are already familiar with the basics, then you can move on to the most interesting stories:

Safe Args is a plugin that goes separately from the Navigation Component, but which was created specifically to make it easier to work with the library. With it, there is no need to specify the destination id and pass parameters through the Bundle, the plugin generates separate classes for this and has a set of extensions to work with them. Let’s figure out how it all works.

Firstly, along with the plugin, there is a new xml tag: <argument>. It is applicable to both action and destination so you can pass and receive parameters in a more convenient way. Secondly, Sage Args generates special classes for each graph action and its arguments. After rebuild you can specify it to the NavController.navigate instead of the action id and argument Bundle.

Show me the code!

<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/graph_user_flow”
app:startDestination=”@id/fragmentUserList”>
<fragment
android:id=”@+id/fragmentUserList”
android:label=”FragmentUserList”
android:name=”com.example.usersList.UserListFragment”
tools:layout=”@layout/fragment_user_list”>

<action
android:id=”@+id/action_to_user_details”
app:destination=”@id/fragmentUserList” >
<argument
android:name=”userId”
app:argType=”integer”
app:nullable=”false” />
</action>
</fragment>
<fragment
android:id=”@+id/fragmentUserDetails”
android:label=”FragmentUserDetails”
android:name=”com.example.usersList.UserDetails”
tools:layout=”@layout/fragment_user_details”/>
</navigation>

Here is a fairly simple graph, where there is a fragment, a nested graph, and a transition from one to other. The only new feature is the <argument>, with which we pass the userid parameter to the users details fragment. Let’s rebuild the project and see what happened.

class UserListFragmentDirections private constructor() {
private data class ActionUserFromListToDetails(
val userId: Int
) : NavDirections {
override fun getActionId(): Int = R.id.actionToUserDetails

override fun getArguments(): Bundle {
val result = Bundle()
result.putInt(“userId”, this.userId)
return result
}
}
companion object {
fun actionToUserDetails(userId: Int): NavDirections =
ActionToUserDetails(userId)
}
}

In the generated folder of the module where the graph is located, we will find wrapper class, which includes all the graph actions with the parameters already included there. In our case, this is going to the user details screen and passing the userId argument there.

navController.navigate(
UserListFragmentDirections.actionToUserDetails(userId)
)

And the parameters in the target destination can be obtained through the new Sage Args extension.

private val args by navArgs<UserDetailsFragmentArgs>()
private val userId by lazy { args.userId }

The argument class itself is also generated into a separate class that contains methods for zipping and unzipping parameters in the Bundle, but it is not so interesting.

Summary

Safe Args is a perfect addition to the Navigation Component because it makes working with transition IDs and handling receiving/sending their arguments much easier. Whether to use it or not it is up to you, but the rest of the story is based on using this plugin. Spoiler: it will bring a lot of problems, but in the end everyone will be happy :)

And now to the most interesting story. Let’s take a look at how to work with the Navigation Component in a multi-module project with Sage Args and iOS-like multistack navigation.

--

--