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

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

使用 Navigator

#

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

dart
child: const Text('Open second screen'),
onPressed: () {
  Navigator.of(context).push(
    MaterialPageRoute<void>(
      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 小部件的应用程序)应使用路由包,例如 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 旨在协同工作。您可以通过声明式路由包(例如 go_router)使用 Router API 进行导航,也可以通过在 Navigator 上调用命令式方法(例如 push()pop())进行导航。

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

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

Web 支持

#

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

更多信息

#

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

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