The Navigation component provides a Kotlin-based domain-specific language, or
DSL, that relies on Kotlin's type-safe
builders
. This API lets you declaratively compose your graph in your Kotlin code, rather
than inside an XML resource. This can be useful if you want to build your app's
navigation dynamically. For example, your app could download and cache a
navigation configuration from an external web service and then use that
configuration to dynamically build a navigation graph in your activity's
onCreate() function.
Dependencies
To use the Kotlin DSL with Fragments, add the following dependency to your app's
build.gradle file:
Groovy
dependencies { def nav_version = "2.10.1" api "androidx.navigation:navigation-fragment-ktx:$nav_version" }
Kotlin
dependencies { val nav_version = "2.10.1" api("androidx.navigation:navigation-fragment-ktx:$nav_version") }
Building a graph
Here is a basic example based on the Sunflower
app. For this
example, we have two destinations: home and plant_detail. The home
destination is present when the user first launches the app. This destination
displays a list of plants from the user's garden. When the user selects one of
the plants, the app navigates to the plant_detail destination.
Figure 1 shows these destinations along with the arguments required by the
plant_detail destination and an action, to_plant_detail, that the app uses
to navigate from home to plant_detail.
home and plant_detail, along with an action that
connects them.Hosting a Kotlin DSL Nav Graph
Before you can build your app's navigation graph, you need a place to host the
graph. This example uses fragments, so it hosts the graph in a
NavHostFragment
inside of a
FragmentContainerView:
<!-- activity_garden.xml -->
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.fragment.app.FragmentContainerView
android:id="@+id/nav_host"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true" />
</FrameLayout>
Notice that the app:navGraph attribute is not set in this example. The graph
isn't defined as a resource in
the res/navigation folder so it needs to be set as part of the onCreate()
process in the activity.
In XML, an action ties together a destination ID with one or more arguments. However, when using the Navigation DSL a route can contain arguments as part of the route. This means that there is no concept of actions when using the DSL.
The next step is to define the routes that you will use when defining your graph.
Create routes for your graph
XML-based navigation graphs are parsed as part
of the Android build process. A numeric constant is created for each id
attribute defined in the graph. These build time generated static IDs are not
available when building your navigation graph at runtime so the Navigation DSL
uses serializable
types instead of
IDs. Each route is represented by a unique type.
When dealing with arguments, these are built into the route type. This lets you have type safety for your navigation arguments.
@Serializable data object Home
@Serializable data class Plant(val id: String)
Build a graph with the NavGraphBuilder DSL
Once you've defined your routes, you can build the navigation graph.
val navController = findNavController(R.id.nav_host_fragment)
navController.graph = navController.createGraph(
startDestination = Home
) {
fragment<HomeFragment, Home> {
label