Android Jetpack架构组件 — Navigation入坑详解
suiw9 2024-11-17 15:46 23 浏览 0 评论
前言
Navigation 直接翻译即为导航,它是 Android Jetpack 组件之一,让单 Activity 应用成为首选架构。应用内Fragment页面的跳转则由 Navigation 来处理,开发者无需在处理 FragmentTransaction 的复杂性以及相关的转场动画。
具体使用
在app的gradle.build中添加依赖:
def nav_version = "2.1.0"implementation "androidx.navigation:navigdef nav_version = "2.1.0"
implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
implementation "androidx.navigation:navigation-ui-ktx:$nav_version"
首先我们定义三个Fragment,分别为Fragment1,Fragment2和Fragment3。实现逻辑为Fragment1点击跳转到Fragment2,Fragment2点击跳转到Fragment3,Fragment3跳转到Fragment1同时点击返回键时也返回到Fragment1。
navigation: 导航视图XML的根结点。里面定义相关fragment的跳转逻辑。
首先需要在res资源目录下新建 navigation 文件夹,右键新建一个Navigation resource file命名为nav_graph_main.xml。
文件左下脚分为两个Tab:Design和Text。Design视图是可视化的,可以直接选择相关fragment。Text视图是我们手写相关配置。
我们看下定义的nav_graph_main.xml文件:
<?xml version="1.0" encoding="utf-8"?>
<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"
app:startDestination="@id/fragment1">
<fragment
android:id="@+id/fragment1"
android:name="com.jetpack.jetpackdemo.navigation.fragment.Fragment1"
android:label="Fragment1"
tools:layout="@layout/fragment1_layout">
<action
android:id="@+id/fragment1_action"
app:destination="@+id/fragment2" />
</fragment>
<fragment
android:id="@+id/fragment2"
android:name="com.jetpack.jetpackdemo.navigation.fragment.Fragment2"
android:label="Fragment2"
tools:layout="@layout/fragment2_layout">
<action
android:id="@+id/fragment2_action"
app:destination="@+id/fragment3" />
</fragment>
<fragment
android:id="@+id/fragment3"
android:name="com.jetpack.jetpackdemo.navigation.fragment.Fragment3"
android:label="Fragment3"
tools:layout="@layout/fragment3_layout">
<action
android:id="@+id/fragment3_action"
app:popUpTo="@id/fragment1" />
</fragment>
</navigation>
navigation根节点中有个startDestination字段,他表示的是默认展示的是哪一个页面。通过fragment标签来定义要路由的相关页面。id为fragment唯一标识。name为包名,必须保证正确。layout为fragment的布局文件,配置后方便在Design视图中查看。
fragment中配置了子节点 action 。action表示的就是具体要路由的行为。同样id也是其唯一标识,destination表示的是目的地,即需要路由到具体的某一个页面。popUpTo表示弹出到某一个页面。action还有其他的属性比如配置动画等,具体请看Demo。
NavHostFragment是导航视图的展示容器。
<fragment
android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="0dp"
android:layout_height="0dp"
app:defaultNavHost="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navGraph="@navigation/nav_graph_main" />
name为固定写法,必须指明为
androidx.navigation.fragment.NavHostFragment
defaultNavHost字段表示是否拦截返回按键操作。
若为true,需要的Activity中重写onSupportNavigateUp方法。
因为默认情况下返回键是不会回退fragment页面的。
override fun onSupportNavigateUp(): Boolean {
return findNavController(R.id.nav_host_fragment).navigateUp()
}
navGraph字段即为我们配置的navigation导航视图。
NavController
通过findNavController来获取NavController,通过controller的navigate或者navigateUp进行页面之间的路由操作。
那么在三个页面的点击按钮的逻辑就是挑战相应的页面:
mBtn.setOnClickListener {
Navigation.findNavController(it).navigate(R.id.fragment1_action)
}
通过指定action的id来告诉Navigation跳转的逻辑。其他页面也是一样。
最终效果:
我们来总结下 navigation、NavHostFragment以及NavController之间的关系。
navigation就是规划了很多的路线,而这些路线需要在NavHostFragment中才能进行展示。展示后这么多的路线该怎么走呢,决定权就在NavController手中了,就像是方向盘一样,控制着该走哪一个路线。
传递参数
在上文中我们讲解了navigation相关的知识,其中还有一个子标签:argument。是用来定义参数的。比如我们在fragment2标签中添加argument标签如下:
<argument
android:name="name"
android:defaultValue="navigation导航"
app:argType="string"
app:nullable="false" />
那么在fragment1跳转到fragment2的时候就可以携带参数了。其中 name 表示参数名称。defaultValue即为默认值。argType为参数的类型。nullable表示是否可以为空。
fragment之间传递参数有两种方式:
- 传统的Bundle方式
- 通过谷歌提供的safeArgs
传统的Bundle方式
通过Bundle来设置和获取参数。
在fragment1中进行设置:
mBtn.setOnClickListener {
//如果要使用 xml中argument的默认值则直接new Bundle() 传入即可
val args = Bundle()
args.putString("name","通过bundle传递参数")
Navigation.findNavController(it).navigate(R.id.fragment1_action, args)
}
在fragment2中进行获取参数:
val args = arguments
val name = args?.getString("name")
mTvName.text = name
这样就可以将参数进行传递了。上面这种方式大家有没有觉得有什么问题呢?
参数名称 “name” 我们在三处进行的手动填写。这样会很容易导致拼写错误以及修改的时候容易漏改。很不友好。所以谷歌给我们提供了一个插件:safeArgs。下面我们来看下具体使用。
safeArgs
首先需要进行配置,在项目的 build.gradle 中添加classpath配置:
dependencies {
classpath 'android.arch.navigation:navigation-safe-args-gradle-plugin:1.0.0'
}
再在app的 build.gradle添加 apply plugin。
apply plugin: 'androidx.navigation.safeargs'
项目重新构建后会知道为fragment生成后缀为 Directions的文件。并为navigation中有 argument 标签的fragment自动生成后缀为Args的文件。
通过后缀为 Directions的文件进行参数的设置。后缀为Args的文件进行参数的获取。
fragment1中进行设置:
mBtn.setOnClickListener {
val args = Fragment1Directions.fragment1Action().setName("通过safeArgs进行参数传递")
Navigation.findNavController(it).navigate(R.id.fragment1_action, args.arguments)
}
fragment2中进行获取:
val name = Fragment2Args.fromBundle(arguments!!).name
mTvName.text = name
这样就完成了fragment之间参数的传递。完全避免了手动设置参数的逻辑。直接通过setter和getter进行参数的操作。
总结
总体来说Navigation的使用并不复杂,它让我们单Activity架构成为可能,无需关心具体的fragment的跳转逻辑。但是同样也是有问题的,通过源码分析我们知道
在NavHostFragment的onCreateView中是创建了FrameLayout,也就是说其实真正的容器是FrameLayout。在创建FragmentNavigator的时候内部使用的是replace这个API,而不是show和hide。这就会导致fragment每次生命周期都会重新执行。所以和ViewModel结合使用效果应该更好。
相关推荐
- 俄罗斯的 HTTPS 也要被废了?(俄罗斯网站关闭)
-
发布该推文的ScottHelme是一名黑客,SecurityHeaders和ReportUri的创始人、Pluralsight作者、BBC常驻黑客。他表示,CAs现在似乎正在停止为俄罗斯域名颁发...
- 如何强制所有流量使用 HTTPS一网上用户
-
如何强制所有流量使用HTTPS一网上用户使用.htaccess强制流量到https的最常见方法可能是使用.htaccess重定向请求。.htaccess是一个简单的文本文件,简称为“.h...
- https和http的区别(https和http有何区别)
-
“HTTPS和HTTP都是数据传输的应用层协议,区别在于HTTPS比HTTP安全”。区别在哪里,我们接着往下看:...
- 快码住!带你十分钟搞懂HTTP与HTTPS协议及请求的区别
-
什么是协议?网络协议是计算机之间为了实现网络通信从而达成的一种“约定”或“规则”,正是因为这个“规则”的存在,不同厂商的生产设备、及不同操作系统组成的计算机之间,才可以实现通信。简单来说,计算机与网络...
- 简述HTTPS工作原理(简述https原理,以及与http的区别)
-
https是在http协议的基础上加了一层SSL(由网景公司开发),加密由ssl实现,它的目的是为用户提供对网站服务器的身份认证(需要CA),以至于保护交换数据的隐私和完整性,原理如图示。1、客户端发...
- 21、HTTPS 有几次握手和挥手?HTTPS 的原理什么是(高薪 常问)
-
HTTPS是3次握手和4次挥手,和HTTP是一样的。HTTPS的原理...
- 一次安全可靠的通信——HTTPS原理
-
为什么HTTPS协议就比HTTP安全呢?一次安全可靠的通信应该包含什么东西呢,这篇文章我会尝试讲清楚这些细节。Alice与Bob的通信...
- 为什么有的网站没有使用https(为什么有的网站点不开)
-
有的网站没有使用HTTPS的原因可能涉及多个方面,以下是.com、.top域名的一些见解:服务器性能限制:HTTPS使用公钥加密和私钥解密技术,这要求服务器具备足够的计算能力来处理加解密操作。如果服务...
- HTTPS是什么?加密原理和证书。SSL/TLS握手过程
-
秘钥的产生过程非对称加密...
- 图解HTTPS「转」(图解http 完整版 彩色版 pdf)
-
我们都知道HTTPS能够加密信息,以免敏感信息被第三方获取。所以很多银行网站或电子邮箱等等安全级别较高的服务都会采用HTTPS协议。...
- HTTP 和 HTTPS 有何不同?一文带你全面了解
-
随着互联网时代的高速发展,Web服务器和客户端之间的安全通信需求也越来越高。HTTP和HTTPS是两种广泛使用的Web通信协议。本文将介绍HTTP和HTTPS的区别,并探讨为什么HTTPS已成为We...
- HTTP与HTTPS的区别,详细介绍(http与https有什么区别)
-
HTTP与HTTPS介绍超文本传输协议HTTP协议被用于在Web浏览器和网站服务器之间传递信息,HTTP协议以明文方式发送内容,不提供任何方式的数据加密,如果攻击者截取了Web浏览器和网站服务器之间的...
- 一文让你轻松掌握 HTTPS(https详解)
-
一文让你轻松掌握HTTPS原文作者:UC国际研发泽原写在最前:欢迎你来到“UC国际技术”公众号,我们将为大家提供与客户端、服务端、算法、测试、数据、前端等相关的高质量技术文章,不限于原创与翻译。...
- 如何在Spring Boot应用程序上启用HTTPS?
-
HTTPS是HTTP的安全版本,旨在提供传输层安全性(TLS)[安全套接字层(SSL)的后继产品],这是地址栏中的挂锁图标,用于在Web服务器和浏览器之间建立加密连接。HTTPS加密每个数据包以安全方...
- 一文彻底搞明白Http以及Https(http0)
-
早期以信息发布为主的Web1.0时代,HTTP已可以满足绝大部分需要。证书费用、服务器的计算资源都比较昂贵,作为HTTP安全扩展的HTTPS,通常只应用在登录、交易等少数环境中。但随着越来越多的重要...
你 发表评论:
欢迎- 一周热门
-
-
Linux:Ubuntu22.04上安装python3.11,简单易上手
-
宝马阿布达比分公司推出独特M4升级套件,整套升级约在20万
-
MATLAB中图片保存的五种方法(一)(matlab中保存图片命令)
-
别再傻傻搞不清楚Workstation Player和Workstation Pro的区别了
-
Linux上使用tinyproxy快速搭建HTTP/HTTPS代理器
-
如何提取、修改、强刷A卡bios a卡刷bios工具
-
Element Plus 的 Dialog 组件实现点击遮罩层不关闭对话框
-
日本组合“岚”将于2020年12月31日停止团体活动
-
SpringCloud OpenFeign 使用 okhttp 发送 HTTP 请求与 HTTP/2 探索
-
tinymce 号称富文本编辑器世界第一,大家同意么?
-
- 最近发表
- 标签列表
-
- dialog.js (57)
- importnew (44)
- windows93网页版 (44)
- yii2框架的优缺点 (45)
- tinyeditor (45)
- qt5.5 (60)
- windowsserver2016镜像下载 (52)
- okhttputils (51)
- android-gif-drawable (53)
- 时间轴插件 (56)
- docker systemd (65)
- slider.js (47)
- android webview缓存 (46)
- pagination.js (59)
- loadjs (62)
- openssl1.0.2 (48)
- velocity模板引擎 (48)
- pcre library (47)
- zabbix微信报警脚本 (63)
- jnetpcap (49)
- pdfrenderer (43)
- fastutil (48)
- uinavigationcontroller (53)
- bitbucket.org (44)
- python websocket-client (47)