使用导航组件将参数安全地传递给嵌套图

GaR*_*eTa 11 android android-navigation android-jetpack-navigation android-navigation-graph

我正在使用 Android Jetpack 导航组件。我有一个带有 id 的嵌套导航图,比如说嵌套图R.id.nested_graph 的第一个Fragment接收一个参数。

<navigation
        android:id="@+id/nested_graph"
        android:label="Nested Graph"
        app:startDestination="@id/firstFragment">
        <fragment
            android:id="@+id/firstFragment"
            android:name="...."
            android:label="....">
            <argument
                android:name="item_id"
                app:argType="integer" />
        </fragment>
        [...]
    </navigation>
Run Code Online (Sandbox Code Playgroud)

如何使用安全 args将参数传递给嵌套图?

目前,我需要在包中手动传递参数,使用直接接收嵌套图的 id 的 API:

        val args = Bundle()
        args.putInt("item_id", itemId)
        navController.navigate(R.id.nested_graph, args)
Run Code Online (Sandbox Code Playgroud)

我想使用安全参数,并执行以下操作:

        val directions = OrigininFragmentDirections.nestedGraph(itemId)
        navController.navigate(directions)
Run Code Online (Sandbox Code Playgroud)

但是在尝试时,我在构建时收到以下错误:

Too many arguments for public final fun nestedGraph(): NavDirections defined 
Run Code Online (Sandbox Code Playgroud)

问题是导航图预处理正在生成工厂方法来创建没有签名中所需参数的NavDirections对象。

嵌套图的声明如下所示:

GaR*_*eTa 16

经过一些反复试验(我认为谷歌没有正式记录,或者至少我找不到它),我发现可以安全地导航到嵌套的导航图传递参数:

您需要argument在嵌套片段本身的根中添加第一个片段所需的XML 对象。

就我而言,带有 idfirstFragment的片段(嵌套图中的第一个片段)接收:

            <argument
                android:name="item_id"
                app:argType="integer" />
Run Code Online (Sandbox Code Playgroud)

因此,我需要将该参数添加到嵌套图中:

<navigation
        android:id="@+id/nested_graph"
        android:label="Nested Graph"
        app:startDestination="@id/firstFragment">

            <argument
                android:name="item_id"
                app:argType="integer" />

        <fragment
            android:id="@+id/firstFragment"
            android:name="...."
            android:label="....">
            <argument
                android:name="item_id"
                app:argType="integer" />
        </fragment>
        [...]
    </navigation>
Run Code Online (Sandbox Code Playgroud)

现在我可以导航到它:

   val directions = OrigininFragmentDirections.nestedGraph(itemId)
        navController.navigate(directions)
Run Code Online (Sandbox Code Playgroud)

请注意,导航图编辑器不会为您执行此操作。这需要在 XML 代码中手动完成。

  • @A.AL 我解决了。你应该将片段参数复制到操作中 (3认同)

小智 11

@GaRRaPeTa 答案几乎是正确的,但如果您使用 SafeArgs 通过操作从主图导航到嵌套图,则还必须向该操作添加一个参数:

<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/graph_main"
    app:startDestination="@id/mainFragment">

    <fragment
        android:id="@+id/mainFragment"
        android:name="com.example.MainFragment">

        <action
            android:id="@+id/toNestedGraph"
            app:destination="@id/graph_nested">

            <argument
                android:name="arg_name"
                app:argType="string" />
        </action>
    </fragment>

</navigation>
Run Code Online (Sandbox Code Playgroud)

  • 如果您使用嵌套图但将其保存在同一个文件中,@GaRRaPeTa 的答案就足够了,并且可能更可取。但是,如果嵌套图移动到其自己的文件并使用“include”标签包含在主图中,则必须将参数复制到此答案中的操作。在后一种情况下,我不需要将参数复制到嵌套图中。 (2认同)