Android Jetpack — Navigation Library (Part2 — Actions)
In the first part of this Series we learned how to use the Architecture Navigation Component. We created two Destinations(ListFragment and DetailFragment) and added a first simple action.
Part 2 — Actions
In this part we will learn to pass data between destinations in a type-safe way and how to define transitions for this actions.
Pass data between destinations
We can use two different ways to pass data to a destination. The old fashioned using a Bundle or the new type-safe way using the safe-args Gradle plugin. Using a Bundle isn’t the best way, it isn’t type-safe and we don’t know which arguments are required. A workaround for this problem is to create static createInstance() methods and other boilerplate code. With the safe-args Gradle plugin this boilerplate code will be generated for us. Let’s have a look.
Dependencies
First of all we have to add the following classpath to our projects build.gradle
buildscript {
repositories {
google()
}
dependencies {
classpath "android.arch.navigation:safe-args-gradle-plugin:1.0.0-alpha01"
}
}
Please notice: i have replaced the
androidx.navigation:safe-args-gradle-plugin
from the documentation withandroid.arch.navigation:navigation-safe-args-gradle-plugin
because the new androidx can’t be resolved at the moment.
And in our app or module build.gradle we have to add
apply plugin: 'androidx.navigation.safeargs'
Arguments
After that we have to define arguments for our destination.
At the moment we can only use four types of arguments inferred, int, string, reference. Someone has already opened an issue for adding more types: see here.
- Select the destination in the navigation graph where the argument is received.
- In the Attributes view click on the + next to the arguments section
- Now we have to choose a name
- We can select a type from the dropdown, default is string
- At least we can choose a default value.
The safeargs plugin now generates simple object and builder classes.
- For the source of our action it will create a class with the Fragment name and the suffix Directions. In our case it will generate ListFragmentDirections. This class has a method with the name of the action detail() which receives the defined arguments.
- For the action it generates a class with the id of the action. In our case Detail
- For the destination fragment it will generate a class with the name of the Fragment and the suffix Args. In our case the generated class is named DetailFragmentArgs.
Code
Now we want to use the generated classes. To navigate to our DetailFragment we have to implement the following code:
val direction = ListFragmentDirections.detail()
direction.setItemId(1)
findNavController().navigate(direction)
First of all we call the action_list_to_detail() method on the generated ListFragmentDirections class. Because we have defined a default value for the argument itemId we have to set it in the next step. Unfortunately the code is generated in Java and doesn’t support default values for methods.
The last line of code is very similar to the one from Navigation Part1. We have to find the NavController and call the navigate method with our NavDirection.
To receive the argument we use the generated DetailFragmentArgs class. In our Detail Fragment we implement the following code:
val detailArgs = DetailFragmentArgs.fromBundle(arguments)
val itemId = detailArgs.itemId
Transitions
If we create an Action we can provide transitions. How to define a animation can you read here: Declare Animations in XML
We will define transitions for our Action from ListFragment to DetailFragment.
There are four properties for transitions:
- enterAnim: the animation for the target (DetailFragment) fragment/activity when we navigate to it
- exitAnim: the animation for the source (ListFragment) fragment/activity when we navigate away from it
- popEnterAnim: the animation for the target(ListFragment) fragment/activity when we press back
- popExitAnim: the animation for the source (DetailFragment) fragment/activity when we press back
Other Navigation Options
We can provide three Launch Options each of it is an equivalent to an Activity Flag:
- launchSingleTop: Activity Flag Single Task
- launchDocument: Activity Flag New Document
- clearTask: Activity Flag Clear Task
Last but not least we can define a PopUpTo Destination. All non-matching destinations should be popped from the back stack if we set it.
Whats next?
In the third Part we will build a more complex App with BottomNavigation and Toolbar and we will learn how they work together with the Navigation Component. We will although define Deeplinks and have a look at testing.