Jetpack系列之Navigation----入门(四)

本文详细介绍了Jetpack Navigation组件中如何在目的地间传递数据,包括定义参数、使用Safe Args和Bundle,以及ProGuard注意事项。此外,还讨论了创建深层链接的显式和隐式方式,以及如何在目的地间添加动画过渡效果。最后,讲解了如何使用NavigationUI更新界面组件,如顶部应用栏、抽屉式导航栏和底部导航栏。
摘要由CSDN通过智能技术生成

在目的地之间传递数据

Navigation 支持您通过定义目的地参数将数据附加到导航操作。例如,用户个人资料目的地可能会根据用户 ID 参数来确定要显示哪个用户。

通常情况下,强烈建议您仅在目的地之间传递最少量的数据。例如,您应该传递键来检索对象而不是传递对象本身,因为在 Android 上用于保存所有状态的总空间是有限的。如果您需要传递大量数据,不妨考虑使用 ViewModel(如在 Fragment 之间共享数据中所述)。

定义目的地参数

如需在目的地之间传递数据,首先请按照以下步骤将参数添加到接收它的目的地来定义参数:

  1. 在 Navigation Editor 中,点击接收参数的目的地。

  2. 在 Attributes 面板中,点击 Add (+)。

  3. 在显示的 Add Argument Link 窗口中,输入参数名称、参数类型、参数是否可为 null,以及默认值(如果需要)。

  4. 点击 Add。请注意,该参数现在会显示在 Attributes 面板的 Arguments 列表中。

  5. 接下来,点击会将您转到此目的地的相应操作。在 Attributes 面板中,您现在应该会在 Argument Default Values 部分中看到新添加的参数。

  6. 您还可以看到该参数已添加到 XML 中。点击 Text 标签页以切换到 XML 视图,就会发现您的参数已添加到接收该参数的目的地。相关示例如下所示:

     <fragment android:id="@+id/myFragment" >
         <argument
             android:name="myArg"
             app:argType="integer"
             android:defaultValue="0" />
     </fragment>
    

在这里插入图片描述

支持的参数类型

Navigation 库支持以下参数类型:
在这里插入图片描述

注意:仅在引用类型中支持对资源的引用。在其他任何类型中使用资源引用都会导致异常

如果参数类型支持 null 值,您可以使用 android:defaultValue="@null" 声明默认值 null

如果您选择其中一种自定义类型,则系统会显示 Select Class 对话框,提示您选择与该类型对应的类。您可以通过 Project 标签页从当前项目中选择类

可以选择 <inferred type>,让 Navigation 库根据提供的值来确定类型
在这里插入图片描述

可以选中 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>

使用 Safe Args 传递安全的数据

这部分前面介绍过两次了,就省略了,没看前面文章的去这里看。

使用 Bundle 对象在目的地之间传递参数

如果您不使用 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()

ProGuard 注意事项

如果要缩减代码,您需要防止在缩减过程中混淆 Parcelable、Serializable 和 Enum 类名称。您可以通过以下两种方式来实现此目的:

使用 @Keep 注释

以下示例说明了如何在模型类定义中添加 @Keep 注释:

@Keep public class ParcelableArg implements Parcelable {
    ... }

@Keep public class SerializableArg implements Serializable {
    ... }

@Keep public enum EnumArg {
    ... }

使用 keepnames 规则

您也可以将 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 创建指向某个目的地的隐式深层链接,如下所示:

  1. 在 Navigation Editor 的 Design 标签页中,选择深层链接的目的地。

  2. 点击 Attributes 面板 Deep Links 部分中的 +。

  3. 在随后显示的 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 的值所定义的变量的查询参数占位符无需匹配。例如,http://www.example.com/users/{id}?arg1={arg1}&arg2={arg2} 与 http://www.example.com/users/4?arg2=28 或 http://www.example.com/users/4?arg1=7 匹配。不过,路径参数并非如此。例如,http://www.example.com/users?arg1=7&arg2=28 就与上述模式不匹配,因为未提供所需的路径参数。
    • 多余的查询参数不会影响深层链接 URI 匹配。例如,即使 URI 模式中未定义 extraneousParam,http://www.example.com/users/{id} 也与 http://www.example.com/users/4?extraneousParam=7 匹配。
  4. (可选)选中 Auto Verify 可要求 Google 验证您是相应 URI 的所有者。如需了解详情,请参阅验证 Android 应用链接

  5. 点击 Add。所选目的地上方会显示链接图标 ,用于表示该目的地具有深层链接。

  6. 点击 Text 标签页,以切换到 XML 视图。已向相应目的地添加嵌套的 < deepLink > 元素:

    <deepLink app:uri="https://www.google.com" />
    

在这里插入图片描述

如需启用隐式深层链接,您还必须向应用的 manifest.xml 文件中添加内容。将一个 < nav-graph > 元素添加到指向现有导航图的 Activity,如以下示例所示。

<?xml version="1.0" encoding
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值