谷歌开发者

Jetpack Navigation 3 | 专为 Compose 打造的全新导航库

Image

作者 / 开发者关系工程师 Don Turner

在应用中的不同屏幕之间导航理应简单明了。然而,构建稳健、可扩展且赏心悦目的导航体验却并非易事。多年来,Jetpack Navigation 库一直是开发者的重要工具,但随着 Android 界面格局的演变,尤其是 Jetpack Compose 的兴起,我们意识到是时候探索一种全新的解决方案了。

我们将在本文为您介绍新推出的 Jetpack Navigation 3,这是一个专为 Compose 打造的全新导航库。为简洁起见,我们将其简称为 Nav3。这个库采用了声明式编程模型和 Compose 状态作为其基本构建模块。

  • 声明式编程模型
    https://developer.android.com/develop/ui/compose/mental-model
  • Compose 状态

    https://developer.android.com/develop/ui/compose/state

为什么要推出新的导航库?

之前的 Jetpack Navigation 库 (有时也称为 Nav2,因为它是第二个主版本) 最初是在 2018 年发布的,彼时还没有 AndroidX 和 Compose 这两个框架。虽然 Nav2 已经很好地实现了最初目标,但我们了解到,在与现代 Compose 开发模式结合使用时,Nav2 存在一些限制。

其中一个关键的限制是仅支持间接观察返回堆栈状态。这意味着可能存在两个事实来源,从而导致应用状态出现不一致的情况。此外,Nav2 的 NavHost 被设计为仅显示一个目标位置 (即返回堆栈中的最顶层目标位置) 以填充可用空间。这使得实现同时显示多个内容窗格的自适应布局 (例如大屏幕上的列表-详情布局) 变得困难。

Image

△ 从单窗格布局切换到多窗格布局可能会带来导航方面的挑战

创立原则

Nav3 基于以下原则构建而成,旨在提供更大的灵活性并提高开发者掌控力:

  • 您掌控返回堆栈: 作为开发者,您将拥有并控制返回堆栈,而不是将控制权交给库。这是一个简单的列表,由 Compose 状态支持。具体而言,Nav3 期望您的返回堆栈为 SnapshotStateList<T>,其中 T 可以是您选择的任何类型。您可以通过添加或删除项目 (T) 来进行导航,状态的变化会被 Nav3 的界面观测到,并自动反映在其界面上。

  • 告别繁琐: 我们深知您不喜欢导航库具有无法访问的内部组件和状态的 "黑匣子" 式设计。Nav3 的设计秉承开放性和可扩展性原则,为您提供构建模块和实用的默认设置。如果您想要自定义导航行为,可以深入到更低的层级,创建您自己的组件和自定义设置。

  • 选择您的构建模块: Nav3 并没有将所有行为嵌入到库中,而是提供了更小巧的组件,您可以组合这些组件来创建更复杂的功能。我们还准备了操作指南,其中介绍了如何组合组件来解决常见的导航挑战。

Image

△ Nav3 Display 组件观测开发者拥有的返回堆栈的变化

  • 深入到更低的层级
    https://developer.android.com/develop/ui/compose/layering
  • 操作指南

    http://github.com/android/nav3-recipes

关键功能

  • 动画: 内置的过渡动画可用于实现目标位置的切换,包括预测性返回。此外,它还拥有支持自定义动画行为的灵活 API,允许在应用和单个屏幕级别覆写动画。

  • 自适应布局: 通过使用灵活布局 API (名为 Scenes),您可在同一布局中渲染多个目标位置 (例如,大屏设备上的列表-详情布局)。您可借此轻松地在单窗格和多窗格布局之间切换。

  • 状态范围限定: 能够将状态限定在返回堆栈中的目标位置范围内,同时还可通过专用 Jetpack lifecycle 库提供可选的 ViewModel 支持。

  • 模块化: API 设计允许将导航代码拆分到多个模块中。这缩短了构建时间并使各个功能模块之间的职责划分更加清晰。

Image

△ 可以轻松实现自定义动画和预测性返回,并且易于针对各个目标位置进行单独的覆写

  • 预测性返回
    https://developer.android.com/develop/ui/compose/system/predictive-back
  • 支持自定义动画行为的灵活 API

    https://developer.android.com/guide/navigation/navigation-3/animate-destinations

  • 灵活布局 API
    https://developer.android.com/guide/navigation/navigation-3/custom-layouts
  • 专用 Jetpack lifecycle 库

    https://developer.android.com/guide/navigation/navigation-3/save-state#scoping-viewmodels

基本代码示例

为了帮助您了解 Nav3 的工作原理,我们准备了简短的代码示例。

// Define the routes in your app and any arguments.data object Homedata class Product(val id: String)// Create a back stack, specifying the route the app should start with.val backStack = remember { mutableStateListOf<Any>(Home) }// A NavDisplay displays your back stack. Whenever the back stack changes, the display updates.NavDisplay(    backStack = backStack,    // Specify what should happen when the user goes back    onBack = { backStack.removeLastOrNull() },    // An entry provider converts a route into a NavEntry which contains the content for that route.    entryProvider = { route ->        when (route) {            is Home -> NavEntry(route) {                Column {                    Text("Welcome to Nav3")                    Button(onClick = {                        // To navigate to a new route, just add that route to the back stack                        backStack.add(Product("123"))                    }) {                        Text("Click to navigate")                    }                }            }            is Product -> NavEntry(route) {                Text("Product ${route.id} ")            }            else -> NavEntry(Unit) { Text("Unknown route: $route") }        }    })

开始使用并分享反馈

首先,您可以查看开发者文档以及操作指南,其中提供了以下示例:

  • 常见导航界面,例如导航边栏或导航栏

  • 条件导航,例如登录流程

  • 使用 Scenes 的自定义布局

  • 开发者文档
    https://goo.gle/nav3
  • 操作指南

    https://github.com/android/nav3-recipes

我们计划在未来为更复杂的用例提供代码示例、技术文档和文章。

Nav3 目前处于 Alpha 阶段,这意味着我们可能会根据反馈修改 API。如果您有任何问题或反馈,欢迎分享给我们:

https://issuetracker.google.com/issues/new?component=1750212&template=2102223

Nav3 为在 Compose 应用中构建现代导航提供了灵活而强大的基础。我们非常期待看到您借此打造的精彩作品。

您可以在 io.google 上查看所有 Google I/O 2025 的精彩更新。

  • io.google

    https://io.google/2025/?utm_source=blogpost&utm_medium=pr&utm_campaign=event&utm_content

Image

Image

Image