If would someone ask what are the main pain point in android development we would say immediately navigation and handling life-cycle. Because of that we are very happy that Google finally decided to do some spring cleaning there. Having Android Architecture Components as part of JetPack should help a lot developers on those main problems. We decided to give a try to Navigation and this is our experience.
Setting up
This part was very straightforward and painless. You just have to add next lines in your app level build.gradle file:
dependencies {
def nav_version = "1.0.0-alpha02"
implementation "android.arch.navigation:navigation-fragment:$nav_version" // use -ktx for Kotlin
implementation "android.arch.navigation:navigation-ui:$nav_version" // use -ktx for Kotlin
}
Making your activity navigation aware
This is our activity layout:
<?xml version="1.0" encoding="utf-8"?>
<layout>
<android.support.constraint.ConstraintLayout
xmlns:android=”http://schemas.android.com/apk/res/android”
xmlns:app=”http://schemas.android.com/apk/res-auto”
android:id=”@+id/constrain_activity_home”
android:layout_width=”match_parent”
android:layout_height=”match_parent”>
<fragment
android:id=”@+id/my_nav_host_fragment”
android:name=”androidx.navigation.fragment.NavHostFragment”
android:layout_width=”match_parent”
android:layout_height=”0dp”
android:layout_weight=”1″
app:defaultNavHost=”true”
app:layout_constraintBottom_toBottomOf=”parent”
app:layout_constraintEnd_toEndOf=”parent”
app:layout_constraintStart_toStartOf=”parent”
app:layout_constraintTop_toTopOf=”parent”
app:navGraph=”@navigation/nav_graph” />
</android.support.constraint.ConstraintLayout>
</layout>
Very important part is to have this 3 lines:
android:name="androidx.navigation.fragment.NavHostFragment"
app:defaultNavHost="true"
app:navGraph="@navigation/nav_graph" />
app:defaultNavHost="true" is important part to make your back button works on expected way. You have to override onSupportNavigateUp in your activity and we don’t know why that is not default behavior.
This will define a place where all of your fragment will be positioned. Now we know where our fragments will exist, but we still need to define first one and flow based on actions on the screen. We define that with next attribute app:navGraph="@navigation/nav_graph" />
Define all fragments and set start one
Now you have to add in your resources navigation and create a file there nav_graph.xml.
In our simple case we had just two fragments and this is how we define those.
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
app:startDestination="@id/listFragment">
<fragment
android:id="@+id/listFragment"
android:name="erevacation.com.userlist_navigation.ui.homescreen.list.ListFragment"
android:label="ListFragment">
</fragment>
<fragment
android:id="@+id/profileFragment"
android:name="erevacation.com.userlist_navigation.ui.homescreen.profile.ProfileFragment"
android:label="ProfileFragment">
</fragment>
</navigation>
Super simple, now system knows that we have two fragments and which one is start destination app:startDestination="@id/listFragment".
Define flow between fragments
We have first to define actions on each fragment. In our case we have only one. When user click on some item from the list we open next fragment.
To do that you have to define actions:
<?xml version=”1.0″ encoding=”utf-8″?>
<navigation xmlns:android=”http://schemas.android.com/apk/res/android”
xmlns:app=”http://schemas.android.com/apk/res-auto”
app:startDestination=”@id/listFragment”>
<fragment
android:id=”@+id/listFragment”
android:name=”erevacation.com.userlist_navigation.ui.homescreen.list.ListFragment”
android:label=”ListFragment”>
<action
android:id=”@+id/action_listFragment_to_profileFragment”
app:destination=”@id/profileFragment” />
</fragment>
<fragment
android:id=”@+id/profileFragment”
android:name=”erevacation.com.userlist_navigation.ui.homescreen.profile.ProfileFragment”
android:label=”ProfileFragment”>
</fragment>
</navigation>
Very simple you have action now and you know destination after that action. You can also define animations there and default arguments there.
Now you just have to use that action where you needed in your code. For us it was click listener implemented in recyclerview adapter.
You don’t need instance of activity or fragment manager, you just simple do next in your adapter:
Navigation.findNavController(it).navigate(R.id.action_listFragment_to_profileFragment, bundle)
And that is it, but you know what, there is more 🙂
Deep linking is so simple now
You have to do two things.
1. Add attribute in fragment part in nav_graph.xml
<fragment
android:id=”@+id/profileFragment”
android:name=”erevacation.com.userlist_navigation.ui.homescreen.profile.ProfileFragment”
android:label=”ProfileFragment”>
<deepLink app:uri=”http://highmobdev.com/profile/{name}/{surname}” />
</fragment>
Using {name} in your url you define attributes for target fragment. That easy 🙂
2. Add attribute in AndroidManifest.xml
<activity
android:name=”.ui.homescreen.HomeActivity”>
<intent-filter>
<action android:name=”android.intent.action.MAIN” />
<category android:name=”android.intent.category.LAUNCHER” />
</intent-filter>
<nav-graph android:value=”@navigation/nav_graph” />
</activity>
And that is all that you need. You don’t have to build stack so your back button works correctly it all done for you.
You can check our code here Userlist Navigation Component
