Flutter 中的自动生成代码是一个非常重要且能极大提升开发效率的特性。它主要通过 代码生成(Code Generation) 来实现,核心是利用 Dart 的 build_runner 工具和 注解(Annotation)。
最常用的场景包括:
- JSON 序列化与反序列化:将 JSON 数据自动转换为 Dart 模型类(Model Class),以及将模型类转换为 JSON。
- 路由生成:为命名路由自动生成路径名称和参数传递代码。
- 依赖注入:自动生成依赖注册和获取的代码。
- 生成数据类:自动生成不可变的数据类(Data Class),包含 copyWith、toString、equals 等方法。
下面我将重点介绍最常用的 JSON 序列化 和 路由生成。
- JSON 序列化 - json_serializable
手动编写 fromJson 和 toJson 方法非常繁琐且容易出错,json_serializable 包可以自动生成这些代码。
步骤一:添加依赖
在 pubspec.yaml 文件中添加以下依赖:
dependencies:
flutter:
sdk: flutter
json_annotation: ^4.8.1 # 最新版本请查阅 pub.dev
dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^2.0.0
build_runner: ^2.4.4 # 用于运行代码生成器
json_serializable: ^6.7.1 # 最新版本请查阅 pub.dev
运行 flutter pub get 获取依赖。
步骤二:创建模型类并使用注解
创建一个简单的用户模型类 user.dart:
import 'package:json_annotation/json_annotation.dart';
// 这个文件会自动生成,第一次运行前会报错,属于正常现象
part 'user.g.dart';
// 告诉生成器这个类需要生成序列化代码
()
class User {
final String name;
final String email;
final int? age; // 可空字段
User({required this.name, required this.email, this.age});
// 从JSON映射创建User实例的工厂方法
// 生成的代码在 _$UserFromJson 中
factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
// 将User实例转换为JSON映射
// 生成的代码在 _$UserToJson 中
Map<String, dynamic> toJson() => _$UserToJson(this);
}
步骤三:运行代码生成器
在项目根目录下打开终端,运行以下命令:
一次性生成:
flutter pub run build_runner build
这条命令会生成 user.g.dart 文件,之后你就可以正常使用 User.fromJson 和 toJson 方法了。
持续监听文件变化并自动生成(推荐在开发时使用):
flutter pub run build_runner watch
使用 watch 后,当你修改了 User 类(比如增加一个字段),保存文件后生成器会自动重新生成 .g.dart 文件,非常方便。
如果之前生成过,需要重新生成(遇到奇怪问题时使用):
flutter pub run build_runner build --delete-conflicting-outputs
–delete-conflicting-outputs 参数会强制删除之前生成的文件并重新生成,解决大部分冲突问题。
最终生成的文件 (user.g.dart):
这个文件是自动生成的,不要手动编辑它。
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'user.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
User _$UserFromJson(Map<String, dynamic> json) => User(
name: json['name'] as String,
email: json['email'] as String,
age: json['age'] as int?,
);
Map<String, dynamic> _$UserToJson(User instance) => <String, dynamic>{
'name': instance.name,
'email': instance.email,
'age': instance.age,
};
- 路由生成 - go_router 或 auto_route
对于大型项目,管理命名路由是一个挑战。这两个包可以帮你自动生成路由相关的代码。
这里以功能强大且流行的 go_router (官方推荐) 为例,它本身通过基于字符串的路由表工作,不需要代码生成,但能很好地管理路由。
如果你需要类型安全、参数自动注入等更高级的功能,可以看 auto_route。
使用 go_router (无需代码生成,但智能管理)
- 添加依赖:
dependencies: go_router: ^11.0.0
- 配置路由:
import 'package:go_router/go_router.dart'; final GoRouter router = GoRouter( routes: <RouteBase>[ GoRoute( path: '/', builder: (BuildContext context, GoRouterState state) => const HomePage(), ), GoRoute( path: '/details/:id', // 使用参数 id builder: (BuildContext context, GoRouterState state) { // 从 state.params 中获取参数 final String id = state.pathParameters['id']!; return DetailsPage(id: id); }, ), ], ); // 在 MaterialApp 中使用 MaterialApp.router( routerConfig: router, ... )
- 导航:
// 跳转到详情页 context.go('/details/123');
go_router 通过智能解析路径来自动处理参数,无需生成代码。
使用 auto_route (需要代码生成)
如果你更喜欢基于注解的、类型安全的路由,auto_route 是更好的选择。它的使用方式和 json_serializable 非常相似。
- 添加依赖 (pubspec.yaml):
dependencies: auto_route: ^7.0.0 dev_dependencies: build_runner: ^2.4.4 auto_route_generator: ^7.0.0
- 使用注解创建路由 (router.dart):
import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; part 'router.gr.dart'; // 将会生成的文件 () class AppRouter extends $AppRouter { List<AutoRoute> get routes => [ AutoRoute(page: HomeRoute.page, initial: true), AutoRoute(page: DetailsRoute.page), ]; } () class HomePage extends StatelessWidget { ... } () class DetailsPage extends StatelessWidget { final String id; DetailsPage({required this.id}); }
- 运行生成器:
它会生成 router.gr.dart 文件,其中包含了 HomeRoute、DetailsRoute 等类以及路径配置。flutter pub run build_runner watch
- 导航 (类型安全):
// 不再需要传递字符串路径 context.pushRoute(DetailsRoute(id: '123'));
总结
场景 推荐包 命令 优点
JSON 序列化 json_serializable build_runner build 避免手写错误,节省时间
路由管理 go_router 无 官方推荐,配置简单,功能强大
类型安全路由 auto_route build_runner build 类型安全,参数自动注入
核心流程:
- 在 pubspec.yaml 中添加依赖(包括 build_runner 这样的开发依赖)。
- 在你的 Dart 代码中使用特定的注解(如 @JsonSerializable, @RoutePage)。
- 在终端运行 flutter pub run build_runner build 或 watch 命令。
- 使用生成的代码(.g.dart 或 .gr.dart 文件)。
学会使用代码生成可以让你从大量重复、易错的代码中解放出来,专注于业务逻辑,是 Flutter 开发者必备的技能。