Flutter 提供了一套完整的系统,用于在不同屏幕之间导航和处理深层链接。不涉及复杂深层链接的小型应用可以使用 Navigator,而具有特定深层链接和导航需求的应用则应使用 Router,以便在 Android 和 iOS 上正确处理深层链接,并在应用在 Web 上运行时与地址栏保持同步。

要配置您的 Android 或 iOS 应用以处理深层链接,请参阅深层链接

使用 Navigator

#

Navigator widget 使用目标平台正确的过渡动画,以堆栈形式显示屏幕。要导航到新屏幕,请通过路由的 BuildContext 访问 Navigator 并调用诸如 push()pop() 等命令式方法。

dart
child: const Text('Open second screen'),
onPressed: () {
  Navigator.of(context).push(
    MaterialPageRoute(builder: (context) => const SecondScreen()),
  );
},

由于 Navigator 维护一个 Route 对象堆栈(代表历史堆栈),push() 方法也接受一个 Route 对象。MaterialPageRoute 对象是 Route 的子类,它为 Material Design 指定了过渡动画。有关如何使用 Navigator 的更多示例,请查阅 Flutter Cookbook 中的导航秘籍,或访问 Navigator API 文档

使用命名路由

#

具有简单导航和深层链接需求的应用可以使用 Navigator 进行导航,并使用 MaterialApp.routes 参数处理深层链接。

dart
child: const Text('Open second screen'),
onPressed: () {
  Navigator.pushNamed(context, '/second');
},

/second 代表在 MaterialApp.routes 列表中声明的命名路由。有关完整示例,请查阅 Flutter Cookbook 中的使用命名路由导航秘籍。

局限性

#

尽管命名路由可以处理深层链接,但其行为始终相同,无法自定义。当平台收到新的深层链接时,无论用户当前位于何处,Flutter 都会将一个新的 Route 推入 Navigator。

此外,Flutter 不支持使用命名路由的应用的浏览器前进按钮。基于这些原因,我们不建议大多数应用使用命名路由。

使用 Router

#

具有高级导航和路由需求的 Flutter 应用(例如使用直接链接到每个屏幕的 Web 应用,或具有多个 Navigator widget 的应用)应使用路由包,例如 go_router,它可以在应用收到新的深层链接时解析路由路径并配置 Navigator

要使用 Router,请切换到 MaterialAppCupertinoApp 上的 router 构造函数,并为其提供 Router 配置。路由包(如 go_router)通常提供路由配置,路由可以按如下方式使用:

dart
child: const Text('Open second screen'),
onPressed: () => context.go('/second'),

由于像 go_router 这样的包是声明式的,因此当收到深层链接时,它们将始终显示相同的屏幕。

Router 和 Navigator 的结合使用

#

RouterNavigator 旨在协同工作。您可以使用 Router API 通过声明式路由包(例如 go_router)进行导航,也可以通过在 Navigator 上调用 push()pop() 等命令式方法进行导航。

当您使用 Router 或声明式路由包进行导航时,Navigator 上的每个路由都是页面支持的,这意味着它是使用 Navigator 构造函数上的 pages 参数从 Page 创建的。相反,通过调用 Navigator.pushshowDialog 创建的任何 Route 都将向 Navigator 添加一个无页面路由。如果您使用路由包,页面支持的路由始终是可深层链接的,而无页面路由则不是。

当一个页面支持的 RouteNavigator 中移除时,其之后的所有无页面路由也会被移除。例如,如果深层链接通过从 Navigator 中移除一个页面支持的路由进行导航,那么之后的所有无页面路由(直到下一个页面支持的路由)也会被移除。

Web 支持

#

使用 Router 类的应用与浏览器 History API 集成,在使用浏览器的后退和前进按钮时提供一致的体验。每当您使用 Router 进行导航时,都会将一个 History API 条目添加到浏览器的历史堆栈中。按下后退按钮会使用逆向时间导航,这意味着用户将被带到之前使用 Router 显示的访问位置。这意味着如果用户从 Navigator 中弹出一个页面,然后按下浏览器后退按钮,则前一个页面会被重新推入堆栈。

更多信息

#

有关导航和路由的更多信息,请查看以下资源:

  • Flutter Cookbook 包含多个导航秘籍,展示了如何使用 Navigator
  • NavigatorRouter API 文档包含有关如何在不使用路由包的情况下设置声明式导航的详细信息。
  • 理解导航,这是 Material Design 文档中的一个页面,概述了设计应用导航的概念,包括前进导航、向上导航和时间顺序导航的解释。
  • 学习 Flutter 新的导航和路由系统,一篇发表在 Medium 上的文章,描述了如何直接使用 Router widget,而无需路由包。
  • Router 设计文档包含 Router API 的动机和设计。