本文首发于微信公众号「Android开发之旅」,欢迎关注 ,获取更多技术干货

Jetpack版Wan-Android项目地址:Android Jetpack架构开发组件化应用实战 欢迎star

Flutter版Wan-Android项目地址:Flutter版Wan-Android 欢迎star

前言

Navigation 直接翻译即为导航,它是 Android Jetpack 组件之一,让单 Activity 应用成为首选架构。应用内Fragment页面的跳转则由 Navigation 来处理,开发者无需在处理 FragmentTransaction 的复杂性以及相关的转场动画。

具体使用

在app的gradle.build中添加依赖:

def 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根节点中有个startDestination字段,他表示的是默认展示的是哪一个页面。通过fragment标签来定义要路由的相关页面。id为fragment唯一标识。name为包名,必须保证正确。layout为fragment的布局文件,配置后方便在Design视图中查看。

fragment中配置了子节点 action 。action表示的就是具体要路由的行为。同样id也是其唯一标识,destination表示的是目的地,即需要路由到具体的某一个页面。popUpTo表示弹出到某一个页面。action还有其他的属性比如配置动画等,具体请看Demo。

NavHostFragment是导航视图的展示容器,

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标签如下:

那么在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 = argumentsval 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!!).namemTvName.text = name

这样就完成了fragment之间参数的传递。完全避免了手动设置参数的逻辑。直接通过setter和getter进行参数的操作。

总结

总体来说Navigation的使用并不复杂,它让我们单Activity架构成为可能,无需关心具体的fragment的跳转逻辑。但是同样也是有问题的,通过源码分析我们知道
在NavHostFragment的onCreateView中是创建了FrameLayout,也就是说其实真正的容器是FrameLayout。在创建FragmentNavigator的时候内部使用的是replace这个API,而不是show和hide。这就会导致fragment每次生命周期都会重新执行。所以和ViewModel结合使用效果应该更好。

扫描下方二维码关注公众号,获取更多技术干货。

更多相关文章

  1. JavaScriptCore与iOS和Android交互
  2. android部分控件应用解析
  3. 【android之View和ViewGroup介绍】
  4. web页面(HTML5)实现发送短信的功能
  5. 【Android】短信管理代码
  6. Android之TextView动态设置图片
  7. Android中webview和js之间的交互及注意事项
  8. Android(安卓)点击EditText以外区域,隐藏键盘
  9. 布局及视图(一)

随机推荐

  1. Android之Application Fundamentals
  2. 塞班将死?Android取之?
  3. Android软键盘softboard(1)
  4. Android(安卓)权限集合
  5. (4.1.25)android学习之布局
  6. Android OpenGL入门
  7. Android(安卓)Material design设计风格
  8. [android] EditText的setError文字不显示
  9. Android IPC机制(四)用ContentProvider进行
  10. Android 开发大坑汇总(持续更新)