从导航图中获取参数
Get argument from navigation graph
我有一个导航图如下:
<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/main_graph"
app:startDestination="@id/jobsFragment">
<fragment
android:id="@+id/jobsFragment"
android:name=".JobsFragment"
android:label="JobsFragment">
<action
android:id="@+id/action_jobsFragment_to_newJobDetailsActivity"
app:destination="@id/newJobDetailsActivity" />
</fragment>
<fragment
android:id="@+id/historyFragment"
android:name=".HistoryFragment"
android:label="HistoryFragment" />
<fragment
android:id="@+id/profileFragment"
android:name=".ProfileFragment"
android:label="ProfileFragment" />
<activity
android:id="@+id/newJobDetailsActivity"
android:name=".NewJobDetailsActivity"
android:label="activity_new_job_details"
tools:layout="@layout/activity_new_job_details">
<!-- This is what I want a reference to -->
<argument
android:name="jobId"
app:argType="string" />
</activity>
</navigation>
目标:以编程方式检索 newJobDetailsActivity
的 argument
name
、jobId
的值,无需引用到 action
。使用当前的 API,我可以通过 action
设置 jobId
而无需知道字符串名称文字。这很好,但对于我希望调用者能够导航到目的地而无需知道调用者附加到哪个组件的情况,它并不理想。这更容易用代码解释。让我们来看看我试图解决的两个场景。
场景A
假设我有一个 RecyclerView.ViewHolder
,其中有一些代码可以从名为 JobsFragment
的 Fragment
导航到名为 NewJobDetailsActivity
的 Activity
点击了。
itemView.setOnClickListener {
itemView.findNavController().navigate(
JobsFragmentDirections.ActionJobsFragmentToNewJobDetailsActivity(jobId)
)
}
如果 RecyclerView.ViewHolder
仅存在于 JobsFragment
中,这很好,但如果我想在将来从其他 Fragment
或 Activity
中重用它,我的代码失败了,因为视图持有者需要引用 JobsFragmentDirections
的 action
才能传递 jobId
参数。
场景B
假设我需要为通知创建 PendingIntent
,并且我想使用导航架构 API。
NavDeepLinkBuilder(context)
.setGraph(R.navigation.main_graph)
.setDestination(R.id.newJobDetailsActivity)
.setArguments(Bundle().apply {
putString("jobId", jobId)
})
.createPendingIntent()
在这种情况下,我不需要对 action
的引用,但情况实际上更糟,因为我找不到对 argument
name
的引用在 main_graph
中,所以我不得不使用字符串文字来指定它。呸
tl;dr:有人知道改善这两种情况的方法吗?有没有办法以编程方式从导航图中获取对 argument
的引用?
依赖项:android.arch.navigation:navigation-fragment-ktx:1.0.0-alpha06
、android.arch.navigation:navigation-ui-ktx:1.0.0-alpha06
插件: androidx.navigation.safeargs
对于第二种情况,您可以使用如下内容:
val args = JobsFragmentArgs.Builder(id).build().toBundle()
NavDeepLinkBuilder(context)
.setGraph(R.navigation.main_graph)
.setDestination(R.id.newJobDetailsActivity)
.setArguments(args)
.createPendingIntent()
对于第一种情况,就我个人而言,我建议从创建适配器的 fragment/activity 传递单击侦听器并将侦听器设置为绑定时的视图持有者。然后你可以为其他 fragments/activities.
以不同的方式实现点击
正如 Emre 在他的回答中提到的那样,有一个 args 构建器可以从生成的目标 *Args
class 调用,然后可以使用参数构建并转换为 Bundle
。实现它的方法不是最漂亮的,但它实现了我想要实现的目标。更新的实现:
场景A
itemView.setOnClickListener {
itemView.findNavController().navigate(
R.id.newJobDetailsActivity,
NewJobDetailsActivityArgs.Builder(jobId)
.build()
.toBundle()
)
}
场景B
NavDeepLinkBuilder(context)
.setGraph(R.navigation.main_graph)
.setDestination(R.id.newJobDetailsActivity)
.setArguments(
NewJobDetailsActivityArgs.Builder(jobId)
.build()
.toBundle()
)
.createPendingIntent()
更新:使用NavDeepLinkBuilder
构建的PendingIntent
点击通知实际上不起作用。参数未传递到目标 Activity
。想知道这是否是导航框架的错误。跟踪此问题 here。
我有一个导航图如下:
<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/main_graph"
app:startDestination="@id/jobsFragment">
<fragment
android:id="@+id/jobsFragment"
android:name=".JobsFragment"
android:label="JobsFragment">
<action
android:id="@+id/action_jobsFragment_to_newJobDetailsActivity"
app:destination="@id/newJobDetailsActivity" />
</fragment>
<fragment
android:id="@+id/historyFragment"
android:name=".HistoryFragment"
android:label="HistoryFragment" />
<fragment
android:id="@+id/profileFragment"
android:name=".ProfileFragment"
android:label="ProfileFragment" />
<activity
android:id="@+id/newJobDetailsActivity"
android:name=".NewJobDetailsActivity"
android:label="activity_new_job_details"
tools:layout="@layout/activity_new_job_details">
<!-- This is what I want a reference to -->
<argument
android:name="jobId"
app:argType="string" />
</activity>
</navigation>
目标:以编程方式检索 newJobDetailsActivity
的 argument
name
、jobId
的值,无需引用到 action
。使用当前的 API,我可以通过 action
设置 jobId
而无需知道字符串名称文字。这很好,但对于我希望调用者能够导航到目的地而无需知道调用者附加到哪个组件的情况,它并不理想。这更容易用代码解释。让我们来看看我试图解决的两个场景。
场景A
假设我有一个 RecyclerView.ViewHolder
,其中有一些代码可以从名为 JobsFragment
的 Fragment
导航到名为 NewJobDetailsActivity
的 Activity
点击了。
itemView.setOnClickListener {
itemView.findNavController().navigate(
JobsFragmentDirections.ActionJobsFragmentToNewJobDetailsActivity(jobId)
)
}
如果 RecyclerView.ViewHolder
仅存在于 JobsFragment
中,这很好,但如果我想在将来从其他 Fragment
或 Activity
中重用它,我的代码失败了,因为视图持有者需要引用 JobsFragmentDirections
的 action
才能传递 jobId
参数。
场景B
假设我需要为通知创建 PendingIntent
,并且我想使用导航架构 API。
NavDeepLinkBuilder(context)
.setGraph(R.navigation.main_graph)
.setDestination(R.id.newJobDetailsActivity)
.setArguments(Bundle().apply {
putString("jobId", jobId)
})
.createPendingIntent()
在这种情况下,我不需要对 action
的引用,但情况实际上更糟,因为我找不到对 argument
name
的引用在 main_graph
中,所以我不得不使用字符串文字来指定它。呸
tl;dr:有人知道改善这两种情况的方法吗?有没有办法以编程方式从导航图中获取对 argument
的引用?
依赖项:android.arch.navigation:navigation-fragment-ktx:1.0.0-alpha06
、android.arch.navigation:navigation-ui-ktx:1.0.0-alpha06
插件: androidx.navigation.safeargs
对于第二种情况,您可以使用如下内容:
val args = JobsFragmentArgs.Builder(id).build().toBundle()
NavDeepLinkBuilder(context)
.setGraph(R.navigation.main_graph)
.setDestination(R.id.newJobDetailsActivity)
.setArguments(args)
.createPendingIntent()
对于第一种情况,就我个人而言,我建议从创建适配器的 fragment/activity 传递单击侦听器并将侦听器设置为绑定时的视图持有者。然后你可以为其他 fragments/activities.
以不同的方式实现点击正如 Emre 在他的回答中提到的那样,有一个 args 构建器可以从生成的目标 *Args
class 调用,然后可以使用参数构建并转换为 Bundle
。实现它的方法不是最漂亮的,但它实现了我想要实现的目标。更新的实现:
场景A
itemView.setOnClickListener {
itemView.findNavController().navigate(
R.id.newJobDetailsActivity,
NewJobDetailsActivityArgs.Builder(jobId)
.build()
.toBundle()
)
}
场景B
NavDeepLinkBuilder(context)
.setGraph(R.navigation.main_graph)
.setDestination(R.id.newJobDetailsActivity)
.setArguments(
NewJobDetailsActivityArgs.Builder(jobId)
.build()
.toBundle()
)
.createPendingIntent()
更新:使用NavDeepLinkBuilder
构建的PendingIntent
点击通知实际上不起作用。参数未传递到目标 Activity
。想知道这是否是导航框架的错误。跟踪此问题 here。