Flutter路由管理插件routefly的使用

发布于 1周前 作者 h691938207 来自 Flutter

Flutter路由管理插件Routefly的使用

Routefly简介

Logo

Routefly是由Flutterando社区创建的基于文件夹的路由管理器,灵感来源于NextJS。它允许你通过在特定目录中组织代码文件来自动创建Flutter应用中的路由。当一个文件被添加到"pages"目录时,它会自动作为一个路由可用。只需要在"lib/app"文件夹内添加适当的文件夹结构。

示例

  • /lib/app/dashboard/dashboard_page.dart => /dashboard
  • /lib/app/users/users_page.dart => /users
  • /lib/app/users/[id]/user_page.dart => /users/2

安装与初始化

1. 添加Routefly包到你的Flutter项目:

flutter pub add routefly

2. 修改你的MaterialApp或CupertinoApp,用MaterialApp.router或CupertinoApp.router替换,并使用Routefly.routerConfig方法配置路由器:

import 'package:routefly/routefly.dart';
import 'my_app.route.dart'; // GENERATED
part 'my_app.g.dart'; // GENERATED

@Main('lib/app')
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp.router(
      routerConfig: Routefly.routerConfig(
        routes: routes, // GENERATED
      ),
    );
  }
}

@Main()接收一个参数作为Routefly用来查找页面的基础文件夹,默认是lib/app

3. 组织你的代码,创建包含*_page.dart文件的文件夹为每个页面。例如:

.
└── app/
    ├── product/
    │   └── product_page.dart
    └── user/
        └── user_page.dart

4. 使用以下命令生成路由:

dart run routefly

每次创建新的带有页面的文件夹时运行此命令以再次生成路由。你也可以使用--watch标志,在向文件夹添加新页面时自动生成路由。

路由分组

在app目录中,嵌套文件夹通常映射到URL路径。然而,你可以标记一个文件夹为Route Group以防止该文件夹被包含在路由的URL路径中。这允许你将路由段和项目文件组织成逻辑组而不影响URL路径结构。可以通过括号包裹文件夹名称来创建路由组:(folderName)

例如:

.
└── app/
    ├── (product)/
        └── home/
            └── home_page.dart

生成的路径为/home

导航

Routefly提供了简单的导航方法:

  • Routefly.navigate('path'): 替换整个路由栈为请求的路径。
  • Routefly.pushNavigate('path'): 在现有栈上添加一条新路由。
  • Routefly.push('path'): 向路由栈添加一条路由。
  • Routefly.pop(): 移除路由栈顶部的路由。
  • Routefly.replace('path'): 将最后一个路由替换为请求的路径。

你还可以使用相对路径。

动态路由

动态路由允许从动态数据创建路由。你可以使用方括号内的动态段,如[id][slugs]。例如,创建一个使用动态段的页面:lib/app/users/[id]/user_page.dart。这将生成路由路径/users/[id]

使用导航命令替换动态段,如Routefly.push('/users/2')

访问页面上的动态参数(id)使用Routefly.query['id']

你也可以使用Routefly.query.params访问段参数,例如Routefly.query.params['search']用于/product?search=Text

自定义过渡

要创建自定义路由过渡,可以在页面文件中定义routeBuilder函数。这允许你基于PageRouteBuilder使用自定义过渡。例如:

Route routeBuilder(BuildContext context, RouteSettings settings) {
  return PageRouteBuilder(
    settings: settings,
    pageBuilder: (_, a1, a2) => const UserPage(),
    transitionsBuilder: (_, a1, a2, child) {
      return FadeTransition(opacity: a1, child: child);
    },
  );
}

你也可以改变全局路由过渡:

return CupertinoApp.router(
  routerConfig: Routefly.routerConfig(
    routes: routes,
    routeBuilder: (context, settings, child) {
      return CupertinoPageRoute(
        settings: settings,
        builder: (context) => child,
      );
    },
  ),
);

布局(RouterOutlet)

布局是支持嵌套路由的页面。所有子路由到布局将作为子节点出现在导航中。要创建布局,创建属于它的文件夹并添加*_layout.dart文件。子文件夹必须位于布局父文件夹内。在布局Widget中添加RouterOutlet(),指定嵌套路由出现的位置。

例如:

class DashboardLayout extends StatelessWidget {
  const DashboardLayout({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: Column(
          children: [
            ListTile(
              title: const Text('Option 1'),
              onTap: () {
                Routefly.navigate(routePaths.dashboard.products);
              },
            ),
            ListTile(
              title: const Text('Option 2'),
              onTap: () {
                Routefly.navigate(routePaths.dashboard.users);
              },
            ),
            const Expanded(child: RouterOutlet()),
          ],
        ),
      ),
    );
  }
}

中间件

中间件是拦截请求的函数,可以更改路由信息,取消或重定向路由请求。例如:

FutureOr<RouteInformation> _guardRoute(RouteInformation routeInformation) {
  if (routeInformation.uri.path == '/guarded') {
    return routeInformation.redirect(Uri.parse('/'));
  }

  return routeInformation;
}

return MaterialApp.router(
  routerConfig: Routefly.routerConfig(
    routes: routes,
    middlewares: [_guardRoute],
  ),
);

404页面

创建名为404的路由,当页面未找到时触发。你可以修改默认的未找到页面路由:

return MaterialApp.router(
  routerConfig: Routefly.routerConfig(
    routes: routes,
    notFoundPath: '/not-found',
  ),
);

如果你有任何问题或需要帮助,请随时联系Flutterando社区。

快乐路由使用Routefly!

完整示例Demo

下面是一个完整的示例demo,展示了如何使用Routefly进行路由管理:

// file: my_app.dart

import 'package:flutter/material.dart';
import 'package:routefly/routefly.dart';
import 'my_app.route.dart'; // GENERATED
part 'my_app.g.dart'; // GENERATED

@Main('lib/app')
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp.router(
      routerConfig: Routefly.routerConfig(
        routes: routes, // GENERATED
      ),
    );
  }
}

// file: lib/app/home/home_page.dart

import 'package:flutter/material.dart';

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Home')),
      body: Center(
        child: Text('Welcome to Home Page'),
      ),
    );
  }
}

// file: lib/app/product/product_page.dart

import 'package:flutter/material.dart';

class ProductPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Product')),
      body: Center(
        child: Text('Welcome to Product Page'),
      ),
    );
  }
}

// file: lib/app/user/user_page.dart

import 'package:flutter/material.dart';

class UserPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('User')),
      body: Center(
        child: Text('Welcome to User Page'),
      ),
    );
  }
}

// Generate routes using the following command:
// dart run routefly --watch

这个示例展示了如何设置Routefly并创建基本页面。你可以根据需要添加更多页面和功能。


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

1 回复

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


当然,以下是如何在Flutter项目中使用routefly插件进行路由管理的示例代码。routefly是一个轻量级的路由管理库,它提供了灵活且易于使用的路由管理功能。

1. 添加依赖

首先,你需要在pubspec.yaml文件中添加routefly依赖:

dependencies:
  flutter:
    sdk: flutter
  routefly: ^最新版本号  # 请替换为当前最新版本号

然后运行flutter pub get来安装依赖。

2. 配置路由

接下来,在你的Flutter应用中配置路由。通常,你会在应用的入口文件(例如main.dart)中进行配置。

import 'package:flutter/material.dart';
import 'package:routefly/routefly.dart';
import 'package:your_app/screens/home_screen.dart';
import 'package:your_app/screens/details_screen.dart';

void main() {
  // 初始化路由表
  final routes = <String, WidgetBuilder>{
    '/': (context) => HomeScreen(),
    '/details': (context) => DetailsScreen(),
  };

  // 使用RouteFly进行路由管理
  runApp(
    MaterialApp.router(
      routeInformationParser: RouteFlyParser(routes.keys.toList()),
      routerDelegate: RouteFlyDelegate(
        routes: routes,
      ),
    ),
  );
}

3. 创建屏幕

创建一些示例屏幕,比如HomeScreenDetailsScreen

home_screen.dart

import 'package:flutter/material.dart';

class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Home Screen'),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            // 导航到详情屏幕
            Navigator.pushNamed(context, '/details');
          },
          child: Text('Go to Details'),
        ),
      ),
    );
  }
}

details_screen.dart

import 'package:flutter/material.dart';

class DetailsScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Details Screen'),
      ),
      body: Center(
        child: Text('This is the details screen.'),
      ),
    );
  }
}

4. 使用路由参数

你也可以传递路由参数。例如,在HomeScreen中传递一个参数到DetailsScreen

修改HomeScreen

import 'package:flutter/material.dart';

class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Home Screen'),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            // 导航到详情屏幕并传递参数
            Navigator.pushNamed(
              context,
              '/details',
              arguments: {'itemId': 123},  // 传递参数
            );
          },
          child: Text('Go to Details'),
        ),
      ),
    );
  }
}

修改DetailsScreen

import 'package:flutter/material.dart';

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

  DetailsScreen({required this.arguments});

  @override
  Widget build(BuildContext context) {
    final itemId = arguments['itemId'] ?? 0;  // 获取传递的参数
    return Scaffold(
      appBar: AppBar(
        title: Text('Details Screen'),
      ),
      body: Center(
        child: Text('Item ID: $itemId'),
      ),
    );
  }
}

修改路由配置

你需要确保路由配置能够处理带参数的路由。由于routefly使用MaterialApp.router,它默认不支持直接传递参数给构造函数。但你可以使用RouteFlyDelegateonGenerateRoute方法来处理这种情况:

void main() {
  final routes = <String, WidgetBuilder>{
    '/': (context) => HomeScreen(),
    // 不再直接在这里创建DetailsScreen实例
    '/details': null,
  };

  runApp(
    MaterialApp.router(
      routeInformationParser: RouteFlyParser(routes.keys.toList()),
      routerDelegate: RouteFlyDelegate(
        routes: routes,
        onGenerateRoute: (settings) {
          if (settings.name == '/details') {
            final args = settings.arguments as Map<String, dynamic>?? {};
            return MaterialPageRoute<void>(
              settings: settings,
              builder: (context) => DetailsScreen(arguments: args),
            );
          }
          return null;
        },
      ),
    ),
  );
}

这样,你就完成了一个基本的Flutter应用,使用routefly进行路由管理,并传递路由参数。这个示例展示了如何配置路由、创建屏幕以及传递和使用路由参数。

回到顶部