跳转至正文

路由和导航

Flutter路由和导航的概览。

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<void>(
      builder: (context) => const SecondScreen(),
    ),
  );
},

由于 Navigator 维护 Route 对象栈(表示历史栈),push() 方法也需要传入 Route 对象。MaterialPageRouteRoute 的子类,用于指定 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 都会在 Navigator 上压入新的 Route

使用命名路由的应用也不支持浏览器的前进按钮。因此,我们不建议大多数应用使用命名路由。请改用 go_router 等路由 package,或将 NavigatorMaterialPageRoute 配合使用。

使用 Router

#

具有高级导航与路由需求(例如 Web 应用为每个界面提供直接链接,或应用包含多个 Navigator widget)的 Flutter 应用,应使用 go_router 等路由 package,以便解析路由路径,并在收到新深层链接时配置 Navigator

要使用 Router,请在 MaterialAppCupertinoApp 上改用 router 构造函数,并提供 Router 配置。go_router 等路由 package 通常提供路由配置,可按如下方式使用路由:

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

由于 go_router 等 package 是声明式的,收到深层链接时始终会显示相同的界面。

同时使用 Router 与 Navigator

#

RouterNavigator 设计为协同工作。你可以通过声明式路由 package(如 go_router)使用 Router API 导航,也可以在 Navigator 上调用 push()pop() 等命令式方法。

使用 Router 或声明式路由 package 导航时,Navigator 上的每条路由都是由 Page 支持(page-backed)的,即通过 Navigator 构造函数的 pages 参数由 Page 创建。反之,通过 Navigator.pushshowDialog 创建的 Route 会向 Navigator 添加无 Page(pageless)路由。若使用路由 package,由 Page 支持的路由始终可深层链接,而无 Page 的路由则不行。

当从 Navigator 移除由 Page 支持Route 时,其后的所有无 Page 路由也会一并移除。例如,若深层链接通过从 Navigator 移除由 Page 支持的路由进行导航,其后(直到下一条由 Page 支持的路由之前)的所有无 Page 路由也会被移除。

Web 支持

#

使用 Router 类的应用会与浏览器 History API 集成,在使用浏览器后退与前进按钮时提供一致的体验。每当你通过 Router 导航,都会在浏览器历史栈中添加一条 History API 记录。按下后退按钮会使用*逆时间顺序导航*,即用户会回到先前通过 Router 显示的访问位置。这意味着若用户从 Navigator 弹出页面后再按浏览器后退按钮,先前的页面会重新压入栈中。

更多信息

#

有关导航与路由的更多信息,请参阅以下资源:

  • The Flutter cookbook includes multiple navigation recipes that show how to use the Navigator.
  • Flutter Cookbook 包含多个导航示例,展示如何使用 Navigator
  • The Navigator and Router API documentation contain details on how to set up declarative navigation without a routing package.
  • NavigatorRouter API 文档说明如何在不使用路由 package 的情况下设置声明式导航。
  • Understanding navigation, a page from the Material Design documentation, outlines concepts for designing the navigation in your app, including explanations for forward, upward, and chronological navigation.
  • 理解导航(Material Design 文档)概述应用导航的设计概念,包括前向、向上与时间顺序导航的说明。
  • Learning Flutter's new navigation and routing system, an article on Medium, describes how to use the Router widget directly, without a routing package.
  • 学习 Flutter 的新导航与路由系统(Medium 文章)介绍如何在不使用路由 package 的情况下直接使用 Router widget。
  • The Router design document contains the motivation and design of the Router API.
  • Router 设计文档包含 Router API 的动机与设计。