JetPack架构---Navigation的使用
Posted 战国剑
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JetPack架构---Navigation的使用相关的知识,希望对你有一定的参考价值。
一、概念
JetPack中的Navigation组件,用于帮助用户实现导航。Navigation组件的主要应用场景是单activity配合多个fragment的场景,简化了过去fragment管理、导航复杂问题,提供了一套统一的标准。
1-0:Navigation的用处
Navigation的使用,有以下好处-取自官网:
- 管理与处理 Fragment 事务。
- 为页面跳转动画提供标准化资源。
- 实现和处理深层链接-DeepLink。
- 简化导航界面模式接入成本(ToolBar等),开发者只需完成极少的额外工作。
- Safe Args - 可在目标之间导航和传递数据时提供类型安全的 Gradle 插件。
Navigation需要在android Studio3.3或更高版本才可使用。
1-1:Navigation的元素
Navigation包含三大关键元素:
(1)导航图(xml格式的导航文件);
(2)NavHost:显示导航图中目标的空白容器;
(3)NavController:控制导航转向的控制器;
Navigation的做法,简单的说,就是把导航图,放在NavHost中,然后使用NavController控制导航的跳转。
二、示例
2-0:添加依赖
def nav_version = "2.3.0-alpha01"
// Java language implementation
implementation "androidx.navigation:navigation-fragment:$nav_version"
implementation "androidx.navigation:navigation-ui:$nav_version"
2-1:在工程的res目录下,新建导航图
res--右键点击-->选择New --> 选择Android Resource File -->在界面中Resource type中选择Navigation,Directory name默认navigation即可,之后填写File name,如nav_graph。-->确认后,在res目录下将新建一个nav_graph.xml文件,也就是导航图。
此时,我们所建立的导航图还是空白的,需要往里添加需要的Fragment。因此新建三个Fragment,分别为AFragment、BFragment、CFragment。
新建导航文件方式:
以上操作后,按界面提示继续操作即可。操作完成后,再看nav_graph.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"
android:id="@+id/nav_graph"
<!--此处指定AFragment作为起始界面-->
app:startDestination="@id/AFragment">
<fragment
<!--每一个Fragment有一个唯一的Id-->
android:id="@+id/AFragment"
android:name="com.test.jetpackdemo.AFragment"
android:label="fragment_a"
tools:layout="@layout/fragment_a">
<action
<!--此处定义了AFragment到CFragment的动作,可以在导航图中通过拖动来实现-->
android:id="@+id/action_AFragment_to_CFragment"
app:destination="@id/CFragment" />
</fragment>
<fragment
android:id="@+id/CFragment"
android:name="com.test.jetpackdemo.CFragment"
android:label="fragment_c"
tools:layout="@layout/fragment_c">
</fragment>
<fragment
android:id="@+id/BFragment"
android:name="com.test.jetpackdemo.BFragment"
android:label="fragment_b"
tools:layout="@layout/fragment_b" />
</navigation>
2-2:新建NavHost
在activity的布局文件中,新建NavHost这个空白容器,默认方式如下:
<fragment
android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:defaultNavHost="true"
app:navGraph="@navigation/nav_graph" />
1、android:name="androidx.navigation.fragment.NavHostFragment",系统提供的NavHostFragment作为容器。
2、app:defaultNavHost="true",表示使用系统提供的默认容器NavHostFragment
3、app:navGraph="@navigation/nav_graph",表示使用的导航图路径
2-3:NavController控制的使用
在AFragment中调用 Navigation.findNavController(nav1).navigate(R.id.CFragment);即可实现从AFragment跳转到CFragment。
一、findNavController有以下三种方式,上方使用的是第3种。
1、NavHostFragment.findNavController(Fragment fragment)
2、Navigation.findNavController(Activity activity, @IdRes int viewId)
3、Navigation.findNavController(View view)
二、navigate(@IdRes int resId) 入参中的resId,可以是目标Fragment的Id,也可以是到目标Fragment的ActionId。
示例到此结束,通过以上的步骤,我们在Activity中管理Fragment的步骤,比未使用Navigation之前,已经有了明显的简化。在代码中不需要commit或者replace添加Fragment,所有的管理操作都隐性的委托给了Navigation。这也是前面提到的第一点好处:处理 Fragment 事务。
三、Navigation的其余特性说明
3-0:为页面跳转动画提供标准化资源
当你为Fragment页面之间的跳转,设置了action后,你可以针对这个action,对Enter、Exit操作加上动画效果。
3-1:实现和处理深层链接-DeepLink
在nav_graph.xml中,你可以对任意的Fragment页面,添加深层链接。所谓深层链接(DeepLink)有两种情况:
1、其他app或者H5,通过特定的隐式Intent方式,打开另一个app的内页;
2、同一个app通过显示的intent方式(如通知栏),打开该app的内页;
DeepLink在场景上应用广泛,如在微信中,点击链接,打开手机上的指定app的内页。可以用于引流、营销等。
Navigation为DeepLink提供了更简便的实现,通过两步即可实现:
1、在Fragment中添加了深层链接。
<fragment
android:id="@+id/CFragment"
android:name="com.test.jetpackdemo.CFragment"
android:label="fragment_c"
tools:layout="@layout/fragment_c">
<!--给CFragment添加deeplink,添加完成后,在外部web等页面输入https://www.baidu1.com/...后将导航到该页面 -->
<deepLink
android:id="@+id/deepLink2"
app:uri="https://www.baidu1.com/params" />
</fragment>
2、在app的AndroidManifest中添加nav-graph标签,指定导航图位置
<activity android:name=".NavActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<!-- 为Activity设置<nav-graph/>标签,deeplink起效需要 -->
<nav-graph android:value="@navigation/nav_graph" />
</activity>
deeplink有一点需要注意,在设置uri时,请带上params。否则,外部跳转到该app时,只会跳转到主页面,而不会到指定的子页面。
3-2:导航栏(包括Toolbar、BottomNavigationView等)的简化实现
可通过NavigationUI.setupWithNavController方法,绑定导航栏与Navigation。替换原有的ViewPage+Fragment等写法。
3-3:Safe Args - 类型安全的传值
1、默认情况下,你可以使用navigate(@IdRes int resId, @Nullable Bundle args)方式传值,还是一个Bundle方式的传值。
在目的页面,如果是Activity,则通过getIntent()取值。如果是Fragment,则通过getArguments()取值。
2、Safe Args方式,需要做一些额外工作。
1、在最外层的build中添加插件navigation-safe-args-gradle-plugin dependencies def nav_version = "2.3.0-alpha01" classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version" 2、在应用层的build中,应用插件apply plugin: "androidx.navigation.safeargs" 3、在nav_graph.xml文件中,可以对每个页面,新增参数。可通过手写,也可通过attribute中配置添加。 4、重新同步并编译工程。假设在CFragment中添加参数,格式如下,会指定参数的类型:<fragment android:id="@+id/CFragment" android:name="com.test.jetpackdemo.CFragment" android:label="fragment_c" tools:layout="@layout/fragment_c"> <argument android:name="str_inC" app:argType="string" /> </fragment>
5、当存在AFragment指向外界的action时,AFragment才会根据插件生成对应的 Directions。如:AFragmentDirections。
假设AFragment指向CFragment,CFragment中有str_inC,类型是String。
那么可以通过:
传值:
AFragmentDirections.ActionAFragmentToCFragment argsInfo = AFragmentDirections.actionAFragmentToCFragment("test"); Navigation.findNavController(nav1).navigate(R.id.action_AFragment_to_CFragment,argsInfo.getArguments());
取值:
CFragmentArgs.fromBundle(getArguments()).getStrInC();
Safe Args方式,因为已经指定了参数类型,并且只能按该类型来传值,所以是类型安全的。只是过于繁琐,非必要情况不建议使用。
Navigation的基本使用已完成。
以上是关于JetPack架构---Navigation的使用的主要内容,如果未能解决你的问题,请参考以下文章
Android Jetpack导航组件——Navigation的使用
说到Jetpack路由组件熟悉的只有ARouter框架?今天带你深入理解功能强大的Navigation架构
说到Jetpack路由组件熟悉的只有ARouter框架?今天带你深入理解功能强大的Navigation架构