Skip to content

代码生成与 build_runner

Dart 的代码生成工具可以自动为你编写模板代码,减少重复劳动。build_runner 是 Dart 生态中最常用的代码生成运行器。

为什么要用代码生成

在 Flutter 开发中,有很多重复性的模板代码:

  • fromJson() / toJson() — JSON 序列化
  • copyWith() / == / hashCode — 不可变数据类
  • Provider 变量声明 — 状态管理
  • 路由表 — 导航

这些代码手写既繁琐又容易出错,代码生成可以自动完成。

build_runner 使用方法

安装

代码生成工具通常作为 dev_dependencies 安装:

bash
flutter pub add dev:build_runner

常用命令

bash
# 一次性生成所有代码
dart run build_runner build

# 监听文件变化,自动重新生成(开发时推荐)
dart run build_runner watch

# 清理生成的文件
dart run build_runner clean

# 删除并重新生成
dart run build_runner build --delete-conflicting-outputs

理解 part 指令

代码生成写法中,你会看到:

dart
part 'user.g.dart';

part 是 Dart 语言的关键字,意思是「这个文件和另一个文件属于同一个库,共享私有成员」。

  • 你写了章节正文(user.dart
  • 模板代码让助手写(user.g.dart
  • part 告诉 Dart:「我们俩合起来才是完整的一章」

关键规则

  • part 'xxx.g.dart' 中的文件名必须与当前文件对应
  • 永远不要手动编辑 .g.dart 文件——每次运行 build_runner 都会重新覆盖
  • 用了注解就必须加上对应的 part 声明

常用代码生成包

json_serializable — JSON 序列化

bash
flutter pub add json_annotation
flutter pub add dev:json_serializable
flutter pub add dev:build_runner
dart
import 'package:json_annotation/json_annotation.dart';
part 'user.g.dart';

@JsonSerializable()
class User {
  final String name;
  final int age;
  final String? email;

  User({required this.name, required this.age, this.email});

  factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
  Map<String, dynamic> toJson() => _$UserToJson(this);
}

freezed — 不可变数据类

freezed 可以自动生成 copyWith==hashCodetoString 等方法:

bash
flutter pub add freezed_annotation
flutter pub add dev:freezed
flutter pub add dev:build_runner
dart
import 'package:freezed_annotation/freezed_annotation.dart';
part 'user.freezed.dart';
part 'user.g.dart';

@freezed
class User with _$User {
  const factory User({
    required String name,
    required int age,
    String? email,
  }) = _User;

  factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
}

使用:

dart
final user = User(name: '张三', age: 25);

// copyWith
final updated = user.copyWith(age: 26);

// == 比较
user == updated;  // false

// JSON 序列化(需要 json_serializable)
final json = user.toJson();
final fromJson = User.fromJson(json);

riverpod_generator — Riverpod 代码生成

bash
flutter pub add riverpod_annotation
flutter pub add dev:riverpod_generator
flutter pub add dev:build_runner
dart
part 'counter.g.dart';

@riverpod
class Counter extends _$Counter {
  @override
  int build() => 0;

  void increment() => state++;
}

// counterProvider 自动生成

代码生成速查

生成内容适用场景
json_serializablefromJson / toJsonAPI 数据模型
freezedcopyWith / == / toString不可变数据类
riverpod_generatorProvider 定义Riverpod 状态管理
go_router_builder路由表类型安全路由

建议

  • 入门阶段:先手动写,理解原理
  • 正式项目:使用代码生成,减少手写错误
  • 开发时用 dart run build_runner watch 自动生成

下一步

  • 测试 — 单元测试 / Widget 测试

基于 Flutter 官方文档整理