Flutter路由管理插件routeborn的使用

Flutter路由管理插件routeborn的使用

简介

routeborn 是一个基于 Flutter 的 Navigator 2.0 的跨平台路由解决方案。它能够轻松处理嵌套导航。

该解决方案基于 Flutter 的 MaterialApp.routerRouterNavigator 组件。

使用方法

基本使用

  1. 决定 Router 的位置:在你的应用中决定 Router 的位置。基本用法是将 MaterialApp.router 作为初始的 App 小部件(例如,使用内部包含 RouterMaterialApp)。其他地方应该直接使用 Router

  2. 定义 RoutebornPage:根据你的应用逻辑在应用中定义 RoutebornPage 类。每个页面都需要有一个 RoutebornPage

    例如,查看示例项目中的 favorites_page.dart 文件。你可以在其中看到扩展了 RoutebornPageFavoritesPage 类。另一个类是 FavoritesPageView,它是一个普通的 StatelessWidget

  3. 定义应用的路由:理想的路由定义可以放在一个名为 routes.dart 的单独文件中(例如,查看示例项目的 routes.dart 文件)。

  4. 创建 NavigationNotifier:在你的应用中某个地方创建 NavigationNotifier,以便在整个应用生命周期内保持其持久性。

    例如,在根节点的小部件树中使用 StatefulWidget,或者使用 InheritedWidget 或任何你喜欢的状态管理机制(示例项目使用 riverpod 包,并将 NavigationNotifier 放置在一个 Provider 中)。

示例代码

import 'package:example/src/home_page.dart';
import 'package:example/src/page_404.dart';
import 'package:example/src/routes.dart';
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:routeborn/routeborn.dart';

void main() {
  runApp(const ProviderScope(child: MyApp()));
}

// 初始页面栈
NavigationStack<NestingBranch> initialPages() => NavigationStack(
      [AppPageNode(page: HomePage())],
    );

// 导航通知器
final navigationNotifierProvider = ChangeNotifierProvider((_) => NavigationNotifier(routes));

// 路由委托
final rootRouterDelegate = Provider((ref) =>
    RoutebornRootRouterDelegate(ref.watch(navigationNotifierProvider)));

class MyApp extends HookWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp.router(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      routerDelegate: useProvider(rootRouterDelegate),
      routeInformationParser: RoutebornRouteInfoParser(
        page404: Page404(),
        initialStackBuilder: initialPages,
        routes: routes,
      ),
    );
  }
}

功能

  • 无需 BuildContext 访问导航
  • 无需 build_runner 减少 CI/CD 慢速问题
  • 基本控制导航栈
    • pushPage, popPage, popUntil, replaceAllWith, replaceLastWith, replaceRootStackWithsetNestingBranch 用于嵌套导航
    • 获取导航栈状态:canPop, isLastPage<T>, containsPage<T>, getNavigationStack 和嵌套导航的 getNestingBranch
  • 嵌套导航
    • 使用 BuildContext 控制父级或子级导航栈
    • 无限嵌套(尽管我无法想象高于三级的嵌套)
  • 内置深度链接
    • 对话框、抽屉和其他类型的路由也可以修改 URL
    • 路径参数
    • 即将支持查询参数
    • 即将支持更新 URL 不改变导航栈(例如,"#introduction" 这样的哈希式导航)
  • 静态声明路由
  • 自动填充栈
  • 单个或多个 Router 用于嵌套导航
  • 即将支持自定义系统返回键处理
  • 即将支持从弹出页面返回参数

限制

  • 每个页面必须包含一些常量路径标记
  • 不支持无限 URL
  • 路由不能是非确定性的

示例用例

在以下导航树结构中,我们可以看到一个可能的导航状态。这是一个虚构的电商应用的例子,也可以在示例应用中看到。

根栈中有三个页面:LoginPageHomePageHelpPageLoginPageHelpPage 是没有嵌套导航的基本页面。

另一方面,HomePage 是一个使用嵌套导航的页面。嵌套导航通过分支实现。每个分支都有自己的页面堆栈。这些堆栈在切换分支时会被保留。

HomePage 在示例中被 HelpPage 覆盖,后者可能是一个包含额外信息的简单页面。当根栈中的 HelpPage 被弹出后,HomePage 将变得可见。

HomePage 页面可能是一个底部导航栏小部件,对应于嵌套导航的分支。这些标签分别是 ShopFavoritesCart,对应于下面的导航树。

保存堆栈

如下面的导航树所示,所有分支都保留它们的导航堆栈。这意味着,当从 Shop 切换到 Favorites 再切回 Shop 时,Shop 分支的堆栈将被保留。在我们的示例中,产品详情页仍然打开。点击 UI 上的后退按钮后,ProductDetailPage 可以被弹出,而 Shop 分支的导航堆栈中仅剩 ShopPage

┌─ LoginPage
├─ HomePage
│   ├─ Branch: Shop
│   │   ├─ ShopPage
│   │   └─ ProductDetailPage
│   ├─ Branch: Favorites
│   │   ├─ FavoritesPage
│   │   └─ ProductDetailPage
│   └─ Branch: Cart
│       └─ CartPage
└─ HelpPage

常见问题解答

是否可以为每个分支使用多个 Router

这是必要的,例如当你使用 Flutter 框架中的 CupertinoTabScaffold 时。每个标签有单独的构建器。每个标签需要一个单独的 Router

每个这样的 Router 都将有一个 RoutebornNestedRouterDelegate 作为路由器委托。每个 RoutebornNestedRouterDelegate 需要传递一个分支作为参数,对应于标签的分支。

在我们的示例中的 home_page.dart 文件中可以看到 CupertinoTabScaffold 的使用示例。

如果你只需要一个 Router 来处理所有分支,则不需要向 RoutebornNestedRouterDelegate 传递分支参数。

如何自定义页面过渡?

所有 RoutebornPage 默认使用 MaterialPageRoutecreateRoute 方法。

因此,你可以使用 Theme 中的 pageTransitionsTheme 自定义所有页面的过渡效果。

示例代码:

MaterialApp(
  theme: ThemeData(
      pageTransitionsTheme: const PageTransitionsTheme(
        builders: <TargetPlatform, PageTransitionsBuilder>{
          TargetPlatform.android: FadeUpwardsPageTransitionsBuilder(),
          TargetPlatform.iOS: CupertinoPageTransitionsBuilder(),
          TargetPlatform.linux: FadeUpwardsPageTransitionsBuilder(),
          TargetPlatform.macOS: CupertinoPageTransitionsBuilder(),
          TargetPlatform.windows: FadeUpwardsPageTransitionsBuilder(),
        },
      )
  )
)

更多关于Flutter路由管理插件routeborn的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter路由管理插件routeborn的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在Flutter中,路由管理对于应用导航至关重要。routeborn 是一个功能强大的路由管理插件,它提供了灵活和可扩展的路由解决方案。以下是如何在Flutter项目中使用 routeborn 进行路由管理的代码示例。

1. 添加依赖

首先,在你的 pubspec.yaml 文件中添加 routeborn 依赖:

dependencies:
  flutter:
    sdk: flutter
  routeborn: ^最新版本号 # 请替换为实际的最新版本号

然后运行 flutter pub get 以获取依赖。

2. 配置 RouteBorn

在你的主应用文件中(通常是 main.dart),配置 RouteBorn

import 'package:flutter/material.dart';
import 'package:routeborn/routeborn.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp.router(
      routerDelegate: RouteBornDelegate(
        routes: <String, RouteBornPageBuilder>{
          '/': (context, settings) => HomePage(),
          '/details': (context, settings) => DetailsPage(arguments: settings.arguments as Map<String, dynamic>),
        },
      ),
      routeInformationParser: RouteBornParser(),
    );
  }
}

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Home Page')),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            Navigator.pushNamed(context, '/details', arguments: {'key': 'value'});
          },
          child: Text('Go to Details'),
        ),
      ),
    );
  }
}

class DetailsPage extends StatelessWidget {
  final Map<String, dynamic> arguments;

  DetailsPage({required this.arguments});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Details Page')),
      body: Center(
        child: Text('Received argument: ${arguments['key']}'),
      ),
    );
  }
}

3. 使用命名路由

在上面的示例中,我们使用了命名路由 //detailsRouteBornDelegate 负责管理这些路由,并根据 URL 路径返回相应的页面。

4. 传递参数

HomePage 中,我们通过 Navigator.pushNamed 方法传递了一个参数给 DetailsPage。在 DetailsPage 中,我们通过构造函数接收这些参数并显示它们。

5. 深度链接和恢复状态

RouteBorn 还支持深度链接和状态恢复。如果你的应用需要处理从外部链接启动并导航到特定页面,或者在应用重新启动时恢复之前的导航状态,RouteBorn 可以帮助你轻松实现这些功能。

例如,你可以通过 URL 启动应用并导航到特定页面:

yourappscheme://details?key=value

然后,在 main.dart 中配置相应的解析逻辑,RouteBorn 会自动处理这些 URL 并导航到正确的页面。

总结

以上示例展示了如何在 Flutter 项目中使用 routeborn 进行路由管理。通过配置 RouteBornDelegateRouteBornParser,你可以轻松地管理应用中的页面导航和参数传递。如果你需要更高级的功能,如嵌套路由、守卫(guard)等,可以参考 routeborn 的官方文档进行深入了解。

回到顶部