| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 移动开发 -> Navigation 的应用实践 -> 正文阅读 |
|
[移动开发]Navigation 的应用实践 |
1.基本使用第一步,添加依赖Navigation的依赖添加:
为了方便在fragment之间传递参数,同时添加Safe Args的依赖,也可以选择不添加,使用Bundle进行fragment间的传递。 Safe Args依赖添加: 顶层 build.gradle 文件中包含以下 classpath
添加插件,选择其一
第二步,创建导航宿主Activity以及需要的Fragment导航宿主是 Navigation 组件的核心部分之一。导航宿主是一个空容器,用户在您的应用中导航时,目的地会在该容器中交换进出。 导航宿主必须派生于 NavHost。Navigation 组件的默认 NavHost 实现 (NavHostFragment) 负责处理 Fragment 目的地的交换。 注意:Navigation 组件旨在用于具有一个主 Activity 和多个 Fragment 目的地的应用。主 Activity 与导航图相关联,且包含一个负责根据需要交换目的地的 NavHostFragment。在具有多个 Activity 目的地的应用中,每个 Activity 均拥有其自己的导航图。 核心部分在于Activity的布局文件:
Activity中如无业务需求,那么一般无需在Activity添加对Navigation的操作。 注意点: android:name 属性包含 NavHost 实现的类名称。 app:navGraph 属性将 NavHostFragment 与导航图相关联。导航图会在此 NavHostFragment 中指定用户可以导航到的所有目的地。 app:defaultNavHost=“true” 属性确保您的 NavHostFragment 会拦截系统返回按钮。请注意,只能有一个默认 NavHost。如果同一布局(例如,双窗格布局)中有多个宿主,请务必仅指定一个默认 NavHost。 第三步,创建导航图导航图是什么呢?在Navigation中,它是包含您的所有目的地和操作的一种资源文件。在Android studio可视化后,如下图所示: 其中,我们可以看到,里面由不同的界面和一系列的箭头连线组成。界面一般是Fragment,连线则是Fragment之间的跳转关系。其中有些连线还有一些向上的箭头,这个是表示在这次跳转中有fragment存在出栈的操作。 查看导航图的代码: 我们从中一步步分析往下。 首先,顶部的是navigation标签,代码如下:
< navigation > 元素是导航图的根元素。当您向图表添加目的地和连接操作时,可以看到相应的 和 元素在此处显示为子元素。如果您有嵌套图表,它们将显示为子 元素。 第四步,创建目的地目的地,就是导航图中的一个个的界面,在Navigation中可以是Fragment,Activity,DialogFragment等… 这里我们主要介绍Fragment目的地。 在navigation标签下添加fragment标签,如下所示:
第五步,创建跳转在navigation中跳转由实现,是每个目的地之间的逻辑连接,Action通常会将一个目的地连接到另一个目的地,当然也有全局Action,此类Action可让您从应用中的任意位置转到特定目的地。 这里我们主要介绍普通的Action。
Action会包含以下参数。
详情:参考链接 调用:
第六步,传递参数使用Safe Args进行传参,如果不使用的话,那么可以用Bundle代替。这里可以跳过。 示例代码:
简单的参数如上所示,由argument标签修饰,
支持的参数类型如下:
如果参数类型支持 null 值,您可以使用 android:defaultValue=“@null” 声明默认值 null。 替换操作中的目的地参数 所有导航至目的地的操作都使用目的地级的参数和默认值。如果需要,您可以通过在操作级定义参数来替换参数的默认值(如果不存在,则设置一个)。此参数必须与目的地中声明的参数具有相同的名称和类型。 以下 XML 展示了如何声明操作并替换上例中的目的地级参数:
启用 Safe Args 后,生成的代码会为每个操作包含以下类型安全的类和方法,以及每个发送和接收目的地。 为生成操作的每一个目的地创建一个类。该类的名称是在源目的地的名称后面加上“Directions”。例如,如果源目的地是名为 SpecifyAmountFragment 的 Fragment,则生成的类的名称为 SpecifyAmountFragmentDirections。 该类会为源目的地中定义的每个操作提供一个方法。 对于用于传递参数的每个操作,都会创建一个 inner 类,该类的名称根据操作的名称确定。例如,如果操作名称为 confirmationAction,,则类名称为 ConfirmationAction。如果您的操作包含不带 defaultValue 的参数,则您可以使用关联的 action 类来设置参数值。 为接收目的地创建一个类。该类的名称是在目的地的名称后面加上“Args”。例如,如果目的地 Fragment 的名称为 ConfirmationFragment,,则生成的类的名称为 ConfirmationFragmentArgs。可以使用该类的 fromBundle() 方法检索参数。 所以以上代码跳转到DynamicParameterFragment并附带参数的写法就如下所示:
官方链接:https://developer.android.google.cn/guide/navigation?hl=zh-cn 2.踩坑记录第一点.navigation下的fragment声明周期Navigation框架下的Fragment压栈时View会被销毁,再进入栈顶时会再次构建View。这就面临一个Activity不会存在的问题:如何恢复View的数据? 例如:常见的RecyclerView也会在入栈的时候被销毁,当用户返回时候,需要重新构建RecyclerView、绑定Adapter, 因此Adapter或者说是列表数据不能丢失,需要在ViewModel或者Fragment类成员变量中保存, 否则就只能再次请求网络加载数据(体验非常糟糕)。Fragment和View分家的问题,用下面的2张生命周期图可以阐释出来: Navigation出现之前官方给出的Fragment生命周期如下图:(注意onDestroyView之处)
Navigation框架下的Fragment生命周期分为 Fragment Lifecycle 和 View Lifecycle ,View Lifecycle被单独拎出来了,原因就在于Navigation框架下的非栈顶的Fragment均会被销毁View, 也即是 A跳转到B页面: A会执行onDestroyView销毁其 View (凡是和View相关的,如:Databinding、RecyclerView都会被销毁) , 但是Fragment本身会存在( Fragment本身的成员变量等 是不会被销毁的 ) 。为啥这样设计, 请参考Navigation的这个 Issue:Navigation, Saving fragment state , 很多人重写Navigation,使其能够保存View。这个例子请参考 起初Jetpack Navigation把我逼疯了,可是后来真香 ,大致的实现就是将官方的replace方式替换为Hide和Show。 但是不建议。 Navigation框架之下的正确状态流转应该是类似这的: A 通过action打开B,A从 onResume转到onDestroyView,B从onAttach执行到onResume, 当B通过系统返回键返回到A时候,A从上图的onCreateView流转到onResume , 此过程中A的View经历销毁和重建,View(binding实例)的对象实例是不一样的,但是Fragment A这个实例始终相同。 这样的场景下,假设A存在一个网络新闻列表RecyclerView, RecyclerView随着View被销毁、重建。 如何保存其中的数据,避免每次返回到A的时候重新刷新数据(造成:上次浏览数据、位置丢失、额外的网络资源消耗), 因此RecyclerView中Adapter的数据项非常关键! 常见的保存方式有: 1、通过Fragment的成员变量 2、ViewModel 。方法2非常合适,在ViewModel的ViewModelScope通过协程请求网络数据,保存在ViewModel(ViewModel生命周期贯穿Fragment),可通过LiveData、普通变量保存数据,在 onViewCreated之后恢复数据。 参考链接:http://www.icodebang.com/article/274205 第二点.返回键监听在业务处理中,经常在一些需要编辑的界面对返回键进行监听,比如当用户编辑了某一内容的时候,需要返回键进行拦截添加一些挽留的Dialog弹窗。 在fragment中我们可以使用如下方法实现。
第三点.Navigation中的返回栈一开始由于对popUpTo参数的理解存在偏差,导致Navigation的返回栈不及预期。这里需要重点把控一些,Navigation在2.3.0版本后就没有了对返回栈清空的操作,所以在2.3.0后需要结合popUpTo与popUpToInclusive来实现清空栈的操作。 popUpTo表示会将返回栈中某个tag的以上的元素出栈。 popUpToInclusive为true表示会弹出tag,false则不会。 第四点.声明周期引发的一系列问题参考:https://mp.weixin.qq.com/s/XdPYjC_6NP-0rmp8Y3hNpg 评论回复不及时,有问题的小伙伴可以进Q群:682963103 提问 |
|
移动开发 最新文章 |
Vue3装载axios和element-ui |
android adb cmd |
【xcode】Xcode常用快捷键与技巧 |
Android开发中的线程池使用 |
Java 和 Android 的 Base64 |
Android 测试文字编码格式 |
微信小程序支付 |
安卓权限记录 |
知乎之自动养号 |
【Android Jetpack】DataStore |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年3日历 | -2025/3/10 9:43:11- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |