构建单Activity的APP——Navigation(中)

这是我参与11月更文挑战的第10天,活动详情查看:2021最后一次更文挑战

上篇文章介绍了Navigation的三大主要概念:NavHost、NavGraph 和 NavController,我们可以通过这些概念快捷地实现以下几个功能:

  • 正确的导航以及回退
  • 添加导航动画
  • 模块化部分导航
  • 方便的页面复用
  • 从应用外跳转至指定页面

不知道以上功能有没有解决你开发的痛点呢,有的话就看下去吧。

从上篇文章的可视化导航图可以看到,NavGraph看起来像一个有向图,任何你在项目中可以走的路径,已经提前规定了,这对于项目开发是一种保障。实际上XML的NavGraph可视化是一种对其数据结构具象化的实现,XMl中所有的属性都可以是用代码实现的,这一点你应该提前知道。

跳转

跳转很简单,就是NavController执行某条导航路线,当你是这条导航的起点,它会将页面替换成终点。

nav_graph.xml

  1. <fragment
  2. android:id="@+id/test1Fragment"
  3. android:name="com.example.navigationexample.ui.test.Test1Fragment"
  4. android:label="Test1Fragment" >
  5. <action
  6. android:id="@+id/action_test1Fragment_to_test2Fragment"
  7. app:destination="@id/test2Fragment" />
  8. </fragment>
  9. <fragment
  10. android:id="@+id/test2Fragment"
  11. android:name="com.example.navigationexample.ui.test.Test2Fragment"
  12. android:label="Test2Fragment" />

Test.kt

  1. findNavController().navigate(R.id.action_test1Fragment_to_test2Fragment)

回退

相关函数如下:

  • popUpToInclusive()
  • popUpTo()
  • java/kt文件中用:NavController.navigateUp()或者NavController.popBackStack()来移除页面堆栈的栈顶页面

回退有三种实现,下面的将用示例来说明每种实现的逻辑。

默认回退

首页假设我们有多个页面(fragment):fA,fB,fC,fD。

nav.xml图中有fA->fB->fC->fD->fB这样一条路。当我们以默认方式走完这条路后,此时页面堆栈中有:A,B,C,D,B(自底到顶)。

当我们使用NavController.navigateUp()或者NavController.popBackStack()后,此时回退栈中就是:A,B,C,D

回退至特定页面(不覆盖目标特定页)

此时回退栈:A,B,C,D。当我们在fD->fB这个action中加上app:popUpTo后,如代码

  1. <action
  2. android:id="@+id/action_fd_to_fb"
  3. app:destination="@id/fb"
  4. app:popUpTo="@+id/fb"/>

再次走完这条路后,页面栈是这样:

A,B,B

回退至特定页面(覆盖目标特定页)

继续使用上面的示例:此时回退栈:A,B,C,D。我们再把app:popUpToInclusive=”true”加上

  1. <action
  2. android:id="@+id/action_fd_to_fb"
  3. app:destination="@id/fb"
  4. app:popUpTo="@+id/fb"
  5. app:popUpToInclusive="true"/>

页面栈就是这样:

A,B

这种方法与上种方法的区别是:旧的FragmentB会不会被删掉。

回退的限制

到了这个时候你可能有点疑惑了,我要是想回传数据从fD到fB怎么办?想用旧的FragmentB实例怎么办?

抱歉,官方原则上并不建议这样做,用Activity和Fragment保存数据和状态是不推荐的,会有数据丢失、状态丢失等隐患。所以在JetPack都会推荐viewmodel保存数据状态等数据。这样看来要不要旧的Fragment实例并没什么必要,在跳转时携带极少数据的情况以外(Navigation传参跳转),用viewmodel持有数据是最佳实践。这也解释了为什么默认情况下,从一个Fragment回退到前一个Fragment用的是replace而不是show了。


文章标签:

原文连接:https://juejin.cn/post/7033762733795311647

相关推荐

Android多版本flavor配置之资源文件和清单文件合并介绍

Android 面试题:说一下 PendingIntent 和 Intent 的区别

Intent 跳转 传递list集合

Google Play 开发者账户被封 如何改代码快速上架

百度APP Android包体积优化实践(二)Dex行号优化

使用ComposeDesktop开发一款桌面端多功能APK工具

一年时间过去了,LiveData真的被Flow代替了吗? LiveData会被废弃吗?

Flutter 绘制探索 | 箭头端点的设计

Android Notes | 开发手记 ing...

Flutter 小技巧之优化使用的 BuildContext

Android原生自定义车牌输入法 附带两种实现思路以及源码 EasyVehicleKeyBoard

Dart(五)—泛型、库使用、async和await关键字

Android启动优化深入解析,全面掌握!

Android技术知识点:如何使用数据绑定来消除findViewById()

ExoPlayer客户端解密m3u8音频\u002F视频

第四届青训营阅读打卡活动来啦,奖品、规则全面升级,快来学习吧

视频直播小窗口(悬浮窗)展示方案

Flutter 2 商城App实战指南(支持Null safety)

LaunchedEffect到底为我们处理了什么问题?

Android View | Canvas详解