导航架构组件 - 将参数数据传递给startDestination

Ahm*_*ged 33 navigation android android-architecture-components android-architecture-navigation

我有一个活动A,它启动活动B传递一些意图数据.活动B托管来自新导航架构组件的导航图.我想将该意图数据作为参数传递给startDestination片段如何做到这一点?

Ell*_*ock 24

TLDR:您必须手动膨胀图形,将键/值添加到defaultArgs,并在图形上设置图形navController.

步骤1

该文档告诉您<fragment>在您Activity的布局中设置标签中的图形.就像是:

<fragment
    android:id="@+id/navFragment"
    android:name="androidx.navigation.fragment.NavHostFragment"
    app:graph="@navigation/nav_whatever"
    app:defaultNavHost="true"
    />
Run Code Online (Sandbox Code Playgroud)

删除线路设置graph=.

第2步

在将显示您的活动中,NavHostFragment像这样膨胀图形:

val navHostFragment = navFragment as NavHostFragment
val inflater = navHostFragment.navController.navInflater
val graph = inflater.inflate(R.navigation.nav_whatever)
Run Code Online (Sandbox Code Playgroud)

navFragment如上所述,您在XML中为片段提供的ID 在哪里.

第3步[至关重要!]

创建一个包以保存要传递给startDestination片段的参数,并将其添加到图的默认参数中:

val bundle = Bundle()
// ...add keys and values
graph.addDefaultArguments(bundle)
Run Code Online (Sandbox Code Playgroud)

第4步

在主机上设置图形navController:

navHostFragment.navController.graph = graph
Run Code Online (Sandbox Code Playgroud)

  • 此解决方案在1.0.0-alpha09中不再起作用。`addDefaultArgument`函数已被删除。 (7认同)

HvS*_*mon 11

它已固定在中1.0.0-alpha07查看详情。

该解决方案与Elliot Schrock的答案类似,但由官方API包装。

我们必须手动充气NavHostFragmentgraph

使用

NavHostFragment.create(R.navigation.graph, args)
Run Code Online (Sandbox Code Playgroud)

要么

navController.setGraph(R.navigation.graph, args)
Run Code Online (Sandbox Code Playgroud)

ARGS是我们要传递给启动目标的数据。


Nij*_*dli 10

以下将数据从官方文档传递到开始目的地部分:

首先,构造一个包含数据的 Bundle:

val bundle = Bundle().apply {
    putString(KEY, "value")
}
Run Code Online (Sandbox Code Playgroud)

接下来,使用以下方法之一将 Bundle 传递到开始目的地:

然后,您应该使用Fragment.getArguments()来检索起始目的地中的数据。

编辑:

您还可以使用FragmentArgs而不是手动创建包,这使得它更方便且类型安全:

navHostFragment.navController.setGraph(R.navigation.graph, MyFragmentArgs(arg).toBundle())
Run Code Online (Sandbox Code Playgroud)

然后在片段中,您可以将 args 检索为:

private val args: PodFragmentArgs by navArgs()
Run Code Online (Sandbox Code Playgroud)

确保您的片段在 navigation.xml 文件中有参数元素:

<fragment
        android:id="@+id/myFragment"
        android:name="MyFragment"
        android:label="fragment_my"
        tools:layout="@layout/fragment_my">
        <argument
            android:name="argName"
            android:defaultValue="@null"
            app:argType="string"
            app:nullable="true" />
</fragment>
Run Code Online (Sandbox Code Playgroud)


Ahm*_*ged 9

好吧,感谢Google团队的Lan Lake,我找到了解决这个问题的方法.假设您有一个活动A,它将使用一些意图数据启动活动B,并且您希望在startDestination中获取该数据,如果您使用安全参数,那么您可以在这里获得两个选项.

StartFragmentArgs.fromBundle(requireActivity().intent?.extras)

从Intent中读取args.如果你不使用安全args,你可以从你自己使用的bundle中提取数据,requireActivity().intent?.extras这将返回你可以使用的Bundle而不是fragment getArguments()方法.这就是我尝试它,一切正常.

  • 你的答案并不完整。当您使用 SafeArgs 设置捆绑包时,它会返回设置所有捆绑包参数的类对象本身。但你没有告诉我们如何取回那包碎片。如果我们使用 fromBundle 它将始终返回一个新对象,因此当您尝试获取它时它将不再具有该值并且它将为 null (3认同)

Pra*_*ngh 8

所以最后,我找到了解决这个问题的方法。

在撰写此答案时,我正在使用 Navigation 2.2.0-alpha01

如果您想将一些数据作为主机活动的参数直接传递到开始目的地,您需要在主机活动的 onCreate() 方法中手动设置您的主机导航图,如下所示:

获取您的导航控制器:

val navController by lazy { findNavController(R.id.<your_nav_host_id>) }
Run Code Online (Sandbox Code Playgroud)

然后在主机活动的 onCreate()

val bundle = Bundle()
bundle.putString("some_argument", "some_value")
navController.setGraph(R.navigation.<you_nav_graph_xml>, bundle)
Run Code Online (Sandbox Code Playgroud)

或者,如果您想将整个意图附加内容按原样传递给 startDestination:

navController.setGraph(R.navigation.<you_nav_graph_xml>, intent.extras)
Run Code Online (Sandbox Code Playgroud)

由于intent.extras将返回Bundle唯一

使用 setGraph() 方法设置导航图时,应避免在 NavHostFragment 定义中设置 app:NavGraph 属性,因为这样做会导致导航图膨胀和设置两次。

在 startDestination 片段中阅读这些参数时:

如果您使用的是Safe Args 插件(非常推荐),则在您的片段中:

private val args by navArgs<DummyFragmentArgs>()
Run Code Online (Sandbox Code Playgroud)

Safe Args 插件将通过将 Args 附加到您的片段名称来生成 Args 类。例如,如果您调用片段,DummyFragment那么 Safe Args 将生成一个名为的类DummyFragmentArgs

Android KTX中navArgs<>定义的扩展函数在哪里

如果您不使用 Android KTX,您可以获得 args 对象,如:

val args = DummyFragmentArgs.fromBundle(arguments!!)
Run Code Online (Sandbox Code Playgroud)

一旦你获得了参数对象,你就可以简单地获取你的参数:

args.someArgument
Run Code Online (Sandbox Code Playgroud)

注意我们"some_argument"是如何作为参数传递的,我们正在阅读它作为someArgument使用安全参数

如果你没有使用 Safe Args(虽然没有理由不使用它),你可以像这样访问你的参数:

arguments?.getString("some_argument")
Run Code Online (Sandbox Code Playgroud)

所有这些都记录在迁移到导航组件文档中:https : //developer.android.com/guide/navigation/navigation-migrate#pass_activity_destination_args_to_a_start_destination_fragment


Joh*_*aul 7

我认为随着1.0.0版本的发布,这种情况再次发生了变化。Google在官方文档中很好地隐藏了这些信息。或者至少我很难找到它,但是在“ 迁移到导航”组件指南中偶然发现了它。这里提到了如何将参数传递给起始目的地:

https://developer.android.com/guide/navigation/navigation-migrate#pass_activity_destination_args_to_a_start_destination_fragment

简而言之

  1. 您必须以编程方式设置导航图:
findNavController(R.id.main_content)
                .setGraph(R.navigation.product_detail_graph, intent.extras)
Run Code Online (Sandbox Code Playgroud)
  1. 不要在NavHostFragment XML声明中设置图形。
  2. 阅读接收方的其他内容:
val args by navArgs<ProductDetailsArgs>()  
val productId = args.productId
Run Code Online (Sandbox Code Playgroud)

更新:谷歌表示,确实缺少将参数传递给初始导航目标的官方文档。希望它会尽快作为导航组件文档的一部分添加。