Navigation 支持您通过定义目的地参数将数据附加到导航操作。例如,用户个人资料目的地可能会根据用户 ID 参数来确定要显示哪个用户。
通常情况下,强烈建议您仅在目的地之间传递最少量的数据。例如,您应该传递键来检索对象而不是传递对象本身,因为在 Android 上用于保存所有状态的总空间是有限的。如果您需要传递大量数据,不妨考虑使用 ViewModel(如在 Fragment 之间共享数据中所述)。
如需在目的地之间传递数据,首先请按照以下步骤将参数添加到接收它的目的地来定义参数:
在 Navigation Editor 中,点击接收参数的目的地。
在 Attributes 面板中,点击 Add (+)。
在显示的 Add Argument Link 窗口中,输入参数名称、参数类型、参数是否可为 null,以及默认值(如果需要)。
点击 Add。请注意,该参数现在会显示在 Attributes 面板的 Arguments 列表中。
接下来,点击会将您转到此目的地的相应操作。在 Attributes 面板中,您现在应该会在 Argument Default Values 部分中看到新添加的参数。
您还可以看到该参数已添加到 XML 中。点击 Text 标签页以切换到 XML 视图,就会发现您的参数已添加到接收该参数的目的地。相关示例如下所示:
<fragment android:id="@+id/myFragment" >
<argument
android:name="myArg"
app:argType="integer"
android:defaultValue="0" />
</fragment>
注意:仅在引用类型中支持对资源的引用。在其他任何类型中使用资源引用都会导致异常
。
如果参数类型支持 null 值,您可以使用 android:defaultValue="@null" 声明默认值 null
。
如果您选择其中一种自定义类型,则系统会显示 Select Class 对话框,提示您选择与该类型对应的类。您可以通过 Project 标签页从当前项目中选择类
。
您可以选择
。
您可以选中 Array,以指明参数应该是所选 Type 值的数组
。请注意,不支持枚举数组和资源引用数组。不论基础类型的 null 性如何,数组始终可为 null
。数组仅支持一个默认值,即“@null”。数组不支持其他任何默认值
。
所有导航至目的地的操作都使用目的地级的参数和默认值。如果需要,您可以通过在操作级定义参数来替换参数的默认值(如果不存在,则设置一个)。此参数必须与目的地中声明的参数具有相同的名称和类型
。
以下 XML 展示了如何声明操作并替换上例中的目的地级参数:
<action android:id="@+id/startMyFragment"
app:destination="@+id/myFragment">
<argument
android:name="myArg"
app:argType="integer"
android:defaultValue="1" />
</action>
这部分前面介绍过两次了,就省略了,没看前面文章的去这里看。
如果您不使用 Gradle,仍然可以使用 Bundle 对象在目的地之间传递参数。创建 Bundle 对象并使用 navigate() 将它传递给目的地,如下所示:
Bundle bundle = new Bundle();
bundle.putString("amount", amount);
Navigation.findNavController(view).navigate(R.id.confirmationAction, bundle);
在接收目的地的代码中,请使用 getArguments() 方法来检索 Bundle 并使用其内容:
TextView tv = view.findViewById(R.id.textViewAmount);
tv.setText(getArguments().getString("amount"));
您可以将数据传递给应用的起始目的地。首先,您必须显式构建一个 Bundle 来存储数据。然后,使用以下方法之一将该 Bundle 传递给起始目的地:
如果您要以编程方式创建 NavHost,请调用 NavHostFragment.create(R.navigation.graph, args),其中 args 是存储数据的 Bundle
。也可以通过调用以下 NavController.setGraph() 重载之一来设置起始目的地参数
:
使用图表 ID:navController.setGraph(R.navigation.graph, args)
使用图表本身:navController.setGraph(navGraph, args)
如需检索起始目的地中的数据,请调用 Fragment.getArguments()。
如果要缩减代码,您需要防止在缩减过程中混淆 Parcelable、Serializable 和 Enum 类名称。您可以通过以下两种方式来实现此目的:
以下示例说明了如何在模型类定义中添加 @Keep 注释:
@Keep public class ParcelableArg implements Parcelable {
... }
@Keep public class SerializableArg implements Serializable {
... }
@Keep public enum EnumArg {
... }
您也可以将 keepnames 规则添加到您的 proguard-rules.pro 文件中,如以下示例中所示:
proguard-rules.pro
...
-keepnames class com.path.to.your.ParcelableArg
-keepnames class com.path.to.your.SerializableArg
-keepnames class com.path.to.your.EnumArg
...
在 Android 中,深层链接是指将用户直接转到应用内特定目的地的链接。
借助 Navigation 组件,您可以创建两种不同类型的深层链接:显式深层链接和隐式深层链接。
显式深层链接是深层链接的一个实例,该实例使用 PendingIntent 将用户转到应用内的特定位置。例如,您可以在通知或应用微件中显示显式深层链接。
当用户通过显式深层链接打开您的应用时,任务返回堆栈会被清除,并被替换为相应的深层链接目的地。 当嵌套图表时,每个嵌套级别的起始目的地(即层次结构中每个 < navigation > 元素的起始目的地)也会添加到相应堆栈中。也就是说,当用户从深层链接目的地按下返回按钮时,他们会返回到相应的导航堆栈,就像从入口点进入您的应用一样。
您可以使用 NavDeepLinkBuilder 类构建 PendingIntent,如以下示例所示。请注意,如果提供的上下文不是 Activity,构造函数会使用 PackageManager.getLaunchIntentForPackage() 作为默认 Activity 启动(如有)。
PendingIntent pendingIntent = new NavDeepLinkBuilder(context)
.setGraph(R.navigation.nav_graph)
.setDestination(R.id.android)
.setArguments(args)
.createPendingIntent();
如果您已有 NavController,您还可以通过 NavController.createDeepLink() 创建深层链接。
隐式深层链接是指应用中特定目的地的 URI。调用 URI(例如,当用户点击某个链接)时,Android 就可以将应用打开到相应的目的地。
在触发隐式深层链接时,返回堆栈的状态取决于是否使用 Intent.FLAG_ACTIVITY_NEW_TASK 标记启动隐式 Intent:
如果该标记已设置,任务返回堆栈就会被清除,并被替换为相应的深层链接目的地。与显式深层链接一样,当嵌套图表时,每个嵌套级别的起始目的地(即层次结构中每个 < navigation > 元素的起始目的地)也会添加到相应堆栈中。也就是说,当用户从深层链接目的地按下返回按钮时,他们会返回到相应的导航堆栈,就像从入口点进入您的应用一样。
如果该标记未设置,您仍会位于触发隐式深层链接时所在的上一个应用的任务堆栈中。在这种情况下,如果按下返回按钮,您会返回到上一个应用;如果按下向上按钮,就会在导航图中的父级目的地上启动应用的任务。
您可以使用 Navigation Editor 创建指向某个目的地的隐式深层链接
,如下所示:
在 Navigation Editor 的 Design 标签页中,选择深层链接的目的地。
点击 Attributes 面板 Deep Links 部分中的 +。
在随后显示的 Add Deep Link 对话框中,输入一个 URI。
请注意以下几点:
没有架构的 URI 会被假定为 http 或 https
。例如,www.google.com 同时与 http://www.google.com 和 https://www.google.com 匹配。形式为 {placeholder_name} 的路径参数占位符与一个或多个字符相匹配
。例如,http://www.example.com/users/{id} 与 http://www.example.com/users/4 匹配。Navigation 组件通过将占位符名称与已定义的参数(为深层链接目的地所定义)相匹配,尝试将占位符值解析为相应的类型。如果没有定义具有相同名称的参数,对参数值使用默认的 String 类型。您可以使用 .* 通配符匹配 0 个或多个字符
。可以使用查询参数占位符代替路径参数,也可以将查询参数占位符与路径参数结合使用
。例如,http://www.example.com/users/{id}?myarg={myarg} 与 http://www.example.com/users/4?myarg=28 匹配。使用默认值或可为 null 的值所定义的变量的查询参数占位符