Flutter路由构建辅助插件go_router_builder的使用
Flutter路由构建辅助插件 go_router_builder
的使用
go_router_builder
是一个用于简化和增强 go_router
插件的代码生成工具。它允许你定义强类型的路由,从而在编译时捕获错误,而不是在运行时。下面将详细介绍如何使用这个插件,并提供完整的示例。
依赖项
首先,在你的 pubspec.yaml
文件中添加以下依赖:
dependencies:
# 其他依赖...
go_router: ^9.0.3
dev_dependencies:
# 其他开发依赖...
build_runner: ^2.0.0
go_router_builder: ^2.3.0
源码结构
为了使用 go_router_builder
,你需要导入 go_router.dart
库,并包含一个指向生成的 Dart 文件的 part
指令。生成的文件名总是 [source_file].g.dart
。
import 'package:go_router/go_router.dart';
part 'main.g.dart';
运行 build_runner
执行一次性的构建命令:
dart run build_runner build
更多信息可以参考 build_runner 的官方文档。
路由定义
每个路由都需要定义为继承自 GoRouteData
的类,并覆盖 build
方法。
class HomeRoute extends GoRouteData {
const HomeRoute();
@override
Widget build(BuildContext context, GoRouterState state) => const HomeScreen();
}
路由树
路由树可以通过在顶级路由上定义属性来创建:
@TypedGoRoute<HomeRoute>(
path: '/',
routes: <TypedGoRoute<GoRouteData>>[
TypedGoRoute<FamilyRoute>(
path: 'family/:fid',
),
],
)
class HomeRoute extends GoRouteData {
const HomeRoute();
@override
Widget build(BuildContext context, GoRouterState state) => const HomeScreen();
}
@TypedGoRoute<LoginRoute>(path: '/login')
class LoginRoute extends GoRouteData {
LoginRoute({this.from});
final String? from;
@override
Widget build(BuildContext context, GoRouterState state) {
return LoginScreen(from: from);
}
}
初始化 GoRouter
代码生成器会将所有顶级路由聚合到一个名为 $appRoutes
的列表中,以便初始化 GoRouter
实例:
final GoRouter router = GoRouter(routes: $appRoutes);
错误处理
你可以使用强类型路由来提供错误处理器:
class ErrorRoute extends GoRouteData {
ErrorRoute({required this.error});
final Exception error;
@override
Widget build(BuildContext context, GoRouterState state) {
return ErrorScreen(error: error);
}
}
final GoRouter routerWithErrorBuilder = GoRouter(
routes: $appRoutes,
errorBuilder: (BuildContext context, GoRouterState state) {
return ErrorRoute(error: state.error!).build(context, state);
},
);
导航
使用代码生成器提供的 go
或 push
方法进行导航:
void onTap() => const FamilyRoute(fid: 'f2').go(context);
返回值
从 go_router
6.5.0 开始,推送一个路由并在随后弹出它可以产生返回值。生成的路由也支持这一功能:
final bool? result = await const FamilyRoute(fid: 'John').push<bool>(context);
查询参数
未在路径中列出的参数表示查询参数:
@TypedGoRoute<LoginRoute>(path: '/login')
class LoginRoute extends GoRouteData {
LoginRoute({this.from});
final String? from;
@override
Widget build(BuildContext context, GoRouterState state) {
return LoginScreen(from: from);
}
}
默认值
对于非空类型的查询参数,可以定义默认值:
@TypedGoRoute<MyRoute>(path: '/my-route')
class MyRoute extends GoRouteData {
MyRoute({this.queryParameter = 'defaultValue'});
final String queryParameter;
@override
Widget build(BuildContext context, GoRouterState state) {
return MyScreen(queryParameter: queryParameter);
}
}
示例应用
下面是一个完整的示例应用,展示了如何使用 go_router_builder
和 go_router
:
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:provider/provider.dart';
import 'shared/data.dart';
part 'main.g.dart';
void main() => runApp(App());
class App extends StatelessWidget {
App({super.key});
final LoginInfo loginInfo = LoginInfo();
static const String title = 'GoRouter Example: Named Routes';
@override
Widget build(BuildContext context) => ChangeNotifierProvider<LoginInfo>.value(
value: loginInfo,
child: MaterialApp.router(
routerConfig: _router,
title: title,
debugShowCheckedModeBanner: false,
),
);
late final GoRouter _router = GoRouter(
debugLogDiagnostics: true,
routes: $appRoutes,
// 根据登录状态重定向
redirect: (BuildContext context, GoRouterState state) {
final bool loggedIn = loginInfo.loggedIn;
final String loginLoc = const LoginRoute().location;
final bool goingToLogin = state.matchedLocation == loginLoc;
if (!loggedIn && !goingToLogin) {
return LoginRoute(fromPage: state.matchedLocation).location;
}
if (loggedIn && goingToLogin) {
return const HomeRoute().location;
}
return null;
},
refreshListenable: loginInfo,
);
}
// 定义路由
@TypedGoRoute<HomeRoute>(
path: '/',
routes: <TypedGoRoute<GoRouteData>>[
TypedGoRoute<FamilyRoute>(
path: 'family/:fid',
routes: <TypedGoRoute<GoRouteData>>[
TypedGoRoute<PersonRoute>(
path: 'person/:pid',
routes: <TypedGoRoute<GoRouteData>>[
TypedGoRoute<PersonDetailsRoute>(path: 'details/:details'),
],
),
],
),
TypedGoRoute<FamilyCountRoute>(path: 'family-count/:count'),
],
)
class HomeRoute extends GoRouteData {
const HomeRoute();
@override
Widget build(BuildContext context, GoRouterState state) => const HomeScreen();
}
@TypedGoRoute<LoginRoute>(
path: '/login',
)
class LoginRoute extends GoRouteData {
const LoginRoute({this.fromPage});
final String? fromPage;
@override
Widget build(BuildContext context, GoRouterState state) =>
LoginScreen(from: fromPage);
}
class FamilyRoute extends GoRouteData {
const FamilyRoute(this.fid);
final String fid;
@override
Widget build(BuildContext context, GoRouterState state) =>
FamilyScreen(family: familyById(fid));
}
class PersonRoute extends GoRouteData {
const PersonRoute(this.fid, this.pid);
final String fid;
final int pid;
@override
Widget build(BuildContext context, GoRouterState state) {
final Family family = familyById(fid);
final Person person = family.person(pid);
return PersonScreen(family: family, person: person);
}
}
class PersonDetailsRoute extends GoRouteData {
const PersonDetailsRoute(this.fid, this.pid, this.details, {this.$extra});
final String fid;
final int pid;
final PersonDetails details;
final int? $extra;
@override
Page<void> buildPage(BuildContext context, GoRouterState state) {
final Family family = familyById(fid);
final Person person = family.person(pid);
return MaterialPage<Object>(
fullscreenDialog: true,
key: state.pageKey,
child: PersonDetailsPage(
family: family,
person: person,
detailsKey: details,
extra: $extra,
),
);
}
}
class FamilyCountRoute extends GoRouteData {
const FamilyCountRoute(this.count);
final int count;
@override
Widget build(BuildContext context, GoRouterState state) =>
FamilyCountScreen(count: count);
}
通过上述步骤,你可以在 Flutter 应用中有效地使用 go_router_builder
来管理复杂的路由系统,并确保类型安全和更清晰的代码结构。
更多关于Flutter路由构建辅助插件go_router_builder的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter路由构建辅助插件go_router_builder的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,关于go_router_builder
这个Flutter路由构建辅助插件,我可以为你提供一个简单的代码示例来展示其使用方式。go_router_builder
是一个帮助开发者快速构建和管理 Flutter 应用中路由的辅助工具。请注意,实际使用时,你需要确保已经将该插件添加到你的 pubspec.yaml
文件中。
首先,确保你的 pubspec.yaml
文件中包含以下依赖项:
dependencies:
flutter:
sdk: flutter
go_router: ^x.y.z # 替换为最新版本号
go_router_builder: ^a.b.c # 替换为最新版本号
然后运行 flutter pub get
来安装依赖。
以下是一个使用 go_router_builder
的简单示例:
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:go_router_builder/go_router_builder.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp.router(
routeInformationParser: _router.routeInformationParser,
routerDelegate: _router.routerDelegate,
);
}
late final GoRouter _router;
@override
void initState() {
super.initState();
_router = GoRouterBuilder()
.addRoute(
path: '/',
name: 'home',
builder: (context, state) => HomeScreen(),
)
.addRoute(
path: '/details/:id',
name: 'details',
builder: (context, state) {
final id = state.params['id']!;
return DetailsScreen(id: id);
},
)
.build();
}
}
class HomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Home')),
body: Center(
child: ElevatedButton(
onPressed: () {
// Navigate to details screen with an example ID
context.goNamed('details', params: {'id': '123'});
},
child: Text('Go to Details'),
),
),
);
}
}
class DetailsScreen extends StatelessWidget {
final String id;
DetailsScreen({required this.id});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Details')),
body: Center(
child: Text('Details for ID: $id'),
),
);
}
}
在这个示例中,我们做了以下几件事:
- 依赖安装:确保在
pubspec.yaml
中添加了go_router
和go_router_builder
依赖。 - 初始化 GoRouter:在
MyApp
的initState
方法中,使用GoRouterBuilder
来构建路由。 - 定义路由:通过
.addRoute
方法定义了两个路由:一个是主页路由,另一个是带有参数的详情页路由。 - 导航:在
HomeScreen
中,使用context.goNamed
方法导航到详情页,并传递一个参数。 - 显示详情:在
DetailsScreen
中,从路由参数中获取 ID 并显示。
这个示例展示了如何使用 go_router_builder
来简化路由的构建和管理过程。当然,根据实际需求,你可能需要添加更多的路由和复杂的逻辑。希望这个示例能帮到你!