导航: 多返回栈 | MAD Skills

导航: 多返回栈 | MAD Skills

欢迎来到第二个关于导航的 MAD Skill 系列 的另一篇文章!本文我们将介绍一个呼声很高的功能,即导航 (Navigation) 对多返回栈的支持。如果您更倾向于视频的形式,请 点击这里 查看视频内容。

概述

假设您的应用使用了 BottomNavigationView。通过这个功能,当用户选择另一个标签页 (Tab) 时,当前标签页的返回栈会被保存,而所选标签页的返回栈会被恢复。

从 2.4.0-alpha01 版本开始,NavigationUI 辅助类不需要改变任何代码即可支持多返回栈。也就是说,如果您的应用使用了为 BottomNavigationViewNavigationView 提供的 setupWithNavController() 方法,则只需要更新依赖库版本,便可默认启用多返回栈。

支持多返回栈

让我们通过这个 仓库 中的高级导航示例来看看实际效果。

该应用由 3 个标签页组成,每个标签页都有它自己的导航流。为了在导航的早期版本中支持多返回栈,我们需要在该示例的 NavigationExtensions 文件中添加一系列辅助函数。通过这些扩展函数,应用可以为每个标签页保持一个单独的 NavHostFragment,每个 NavHostFragment 带有它自己的返回栈,当用户切换标签页时,应用在不同的 NavHostFragment 之间进行切换。

让我们看看如果移除这些扩展函数会发生什么。为此我删除了 NavigationExtensions 类,在所有使用它的地方都替换为 NavigationUI 中标准的 setupWithNavController() 方法以将我们的 BottomNavigationView 连接到 NavController 上。

class MainActivity : AppCompatActivity() {
 
   private lateinit var navController: NavController
   private lateinit var appBarConfiguration: AppBarConfiguration
 
   override fun onCreate(savedInstanceState: Bundle?) {
       super.onCreate(savedInstanceState)
       setContentView(R.layout.activity_main)
 
       val navHostFragment = supportFragmentManager.findFragmentById(
           R.id.nav_host_container
       ) as NavHostFragment
       navController = navHostFragment.navController
 
       // 使用 navController 设置 bottomNavigationView
       val bottomNavigationView = findViewById<BottomNavigationView>(R.id.bottom_nav)
       bottomNavigationView.setupWithNavController(navController)
 
       // 使用 navController 设置 ActionBar 以及 3 个一级目的地页面
       appBarConfiguration = AppBarConfiguration(
           setOf(R.id.titleScreen, R.id.leaderboard,  R.id.register)
       )
       val toolbar = findViewById<Toolbar>(R.id.toolbar)
       setSupportActionBar(toolbar)
       toolbar.setupWithNavController(navController, appBarConfiguration)
   }
 
   override fun onSupportNavigateUp(): Boolean {
       return navController.navigateUp(appBarConfiguration)
   }
}

同时,我使用 include 标签将 3 个单独的导航图合并为一个图。现在我们的 Activity 布局只包含一个带有单个导航图的 NavHostFragment

<navigation
   xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto"
   android:id="@+id/nav_graph"
   app:startDestination="@+id/home">

   <include app:graph="@navigation/home"/>
   <include app:graph="@navigation/list"/>
   <include app:graph="@navigation/form"/>

</navigation>

当我运行应用时,这次底部标签页不再保持它们的状态,并会在我切换到其他标签页时重置它的返回栈。由于移除了 NavigationExtensions,该应用不再支持多返回栈。

现在我将更新 navigation 和 fragment 依赖库的版本。

// fragment 最新版本 https://developer.android.google.cn/jetpack/androidx/releases/fragment?hl=en
// navigation 最新版本 https://developer.android.google.cn/jetpack/androidx/releases/navigation?hl=en

versions.fragment = "1.4.0-alphaXXX"
versions.navigation =  "2.4.0-alphaXXX"

Gradle sync 完成后,我再次运行应用,这时当我导航至其他标签页,可以看到每个标签页都保持了它的状态。注意这个行为是默认启用的。

最后,让我们运行测试来验证是否一切正常。该应用已经拥有一些验证多返回栈行为的测试。我运行 BottomNavigationTest 并观察每个底部导航行为测试的运行。

瞧,我们所有测试都通过了!

小结

就是这样!如果您的应用使用 BottomNavigationViewNavigationView,并且您一直在等待支持多返回栈,您所需要做的仅仅是更新 navigation 和 fragment 依赖库,不需要改变任何代码!

如果您需要进一步的自定义,也有新的 API 支持保存和恢复返回栈。请参阅我们之前的推文《Android 多返回栈技术详解》。

如果您想了解更多有关底层 API 以及需要修改哪些内容以支持多返回栈的信息,请参阅我们之前的推文《全新的 Fragment: 使用新的状态管理器》。

感谢您关注本导航系列!

欢迎您 点击这里 向我们提交反馈,或分享您喜欢的内容、发现的问题。您的反馈对我们非常重要,感谢您的支持!

版权声明

禁止一切形式的转载-禁止商用-禁止衍生 申请授权

脉脉不得语
脉脉不得语
Zhengzhou Website
Android Developer | https://androiddevtools.cn and https://androidweekly.io Funder | GDG Zhengzhou Funder & Ex Organizer | http://Toast.show(∞) Podcast Host

你已经成功订阅到 Android 开发技术周报
太棒了!接下来,完成检验以获得全部访问权限 Android 开发技术周报
欢迎回来!你已经成功登录了。
Unable to sign you in. Please try again.
成功!您的帐户已完全激活,您现在可以访问所有内容。
Error! Stripe checkout failed.
Success! Your billing info is updated.
Error! Billing info update failed.
🍗