Search code examples
androidkotlinandroid-jetpacknavigation-framework

How to map NavArgs to NavArgument?


The issue I encountered is related to setting navigation graph programatically. What I want to achieve is to decide in Activity which fragment should be a start destination. What's more, each of these fragments have additional arguments.

Let's say we have such navigation graph:

<?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"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/nav_graph">

    <fragment
        android:id="@+id/fragment1"
        android:name="com.mypackage.Fragment1"
        tools:layout="@layout/layout_fragment1">

        <argument
            android:name="argument1"
            app:argType="int" />

    </fragment>

    <fragment
        android:id="@+id/fragment2"
        android:name="com.mypackage.Fragment2"
        tools:layout="@layout/layout_fragment2">

        <argument
            android:name="argument2"
            app:argType="string" />

    </fragment>

</navigation>

If we use Safe Args plugin (androidx.navigation.safeargs.kotlin), two classes will be generated: Fragment1Args and Fragment2Args, both implementing NavArgs interface.

Now because we need to decide which fragment should became start destination, we need to make graph programatically:

val graph = navController.navInflater.inflate(R.navigation.nav_graph)
if (someCondition) {
    graph.startDestination = R.id.fragment1
} else {
    graph.startDestination = R.id.fragment2
}
navController.graph = graph

But Fragment1 and Fragment2 requires some additional arguments, so we need somehow to add them to graph. It turns out that graph has method addArguments(NavArguments), but as you see it's not NavArgs interface. Question is how to set these arguments properly that Fragment1 or Fragment2 will be able to extract?

I'm using 1.0.0-rc02 version of navigation framework.


Solution

  • When you add <argument> tag to your navigation XML, it is already creating the NavArgument classes when you call inflate(), so there's nothing you need to do to the graph in order to pass arguments to the start destination.

    Instead, you should use setGraph(NavGraph, Bundle) to set the graph and pass initial arguments to the start destination.

    // Construct your Bundle of arguments
    val bundle = bundleOf()
    // set the graph with specific arguments for the start destination
    navController.setGraph(graph, bundle)