使用导航组件将参数安全地传递给嵌套图
Pass arguments safely to nested graph with Navigation Component
我正在使用 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>
如何使用安全参数将参数传递给嵌套图?
目前,我需要在bundle中手动传递参数,使用直接接收嵌套图id的API:
val args = Bundle()
args.putInt("item_id", itemId)
navController.navigate(R.id.nested_graph, args)
我想使用安全参数,并执行如下操作:
val directions = OrigininFragmentDirections.nestedGraph(itemId)
navController.navigate(directions)
但是在尝试时,我在构建时收到以下错误:
Too many arguments for public final fun nestedGraph(): NavDirections defined
问题是导航图预处理正在生成工厂方法来创建 NavDirections
对象 而签名中没有 所需的参数。
嵌套图的声明如下所示:
经过反复试验(我认为 Google 没有正式记录,或者至少我找不到它),我发现导航到嵌套导航图可以安全地传递参数可以做到:
您需要在嵌套片段本身的根中添加第一个片段期望的 argument
XML 对象。
在我的例子中,id 为 firstFragment
的片段是嵌套图中的第一个片段接收到:
<argument
android:name="item_id"
app:argType="integer" />
因此,我需要将该参数添加到嵌套图中:
<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>
现在我可以导航到它:
val directions = OrigininFragmentDirections.nestedGraph(itemId)
navController.navigate(directions)
请注意,导航图编辑器不会为您做这件事。这需要在 XML 代码中手动完成。
@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>
我正在使用 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>
如何使用安全参数将参数传递给嵌套图?
目前,我需要在bundle中手动传递参数,使用直接接收嵌套图id的API:
val args = Bundle()
args.putInt("item_id", itemId)
navController.navigate(R.id.nested_graph, args)
我想使用安全参数,并执行如下操作:
val directions = OrigininFragmentDirections.nestedGraph(itemId)
navController.navigate(directions)
但是在尝试时,我在构建时收到以下错误:
Too many arguments for public final fun nestedGraph(): NavDirections defined
问题是导航图预处理正在生成工厂方法来创建 NavDirections
对象 而签名中没有 所需的参数。
嵌套图的声明如下所示:
经过反复试验(我认为 Google 没有正式记录,或者至少我找不到它),我发现导航到嵌套导航图可以安全地传递参数可以做到:
您需要在嵌套片段本身的根中添加第一个片段期望的 argument
XML 对象。
在我的例子中,id 为 firstFragment
的片段是嵌套图中的第一个片段接收到:
<argument
android:name="item_id"
app:argType="integer" />
因此,我需要将该参数添加到嵌套图中:
<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>
现在我可以导航到它:
val directions = OrigininFragmentDirections.nestedGraph(itemId)
navController.navigate(directions)
请注意,导航图编辑器不会为您做这件事。这需要在 XML 代码中手动完成。
@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>