Flutter插件功能集成插件merging_builder的使用
Flutter插件功能集成插件merging_builder
的使用
简介
源代码生成在构建和维护大量数据模型、数据访问对象、小部件等时已经成为一种重要的软件开发工具。源代码生成的前提是我们可以在编译时指定(希望是少量的)细节,并在构建过程中充实其余的类和方法。
merging_builder
库提供了两个合成输入生成器类:
MergingBuilder
读取多个输入文件并将合并后的输出写入一个输出文件。该生成器提供按反向拓扑顺序排序输入文件的选项。StandaloneBuilder
读取一个或多个输入文件并将独立文件写入自定义位置。这里的“独立”意味着输出文件可以写入自定义文件夹,不仅扩展名,而且输出文件的名称都可以配置。
使用步骤
1. 添加依赖项
在定义生成器的包的pubspec.yaml
文件中添加merging_builder
和build
作为依赖项。在这个例子中,生成器还需要analyzer
和source_gen
包。
dependencies:
merging_builder: ^latest_version
build: ^latest_version
analyzer: ^latest_version
source_gen: ^latest_version
2. 创建自定义生成器
创建一个继承自MergingGenerator
的自定义生成器。用户需要实现generateItemForAnnotatedElement
和generateMergedContent
方法。
import 'dart:async';
import 'package:analyzer/dart/element/element.dart';
import 'package:build/build.dart' show BuildStep;
import 'package:merging_builder/merging_builder.dart';
import 'package:quote_buffer/quote_buffer.dart';
import 'package:source_gen/source_gen.dart' show ConstantReader;
import '../annotations/add_names.dart';
class AddNamesGenerator extends MergingGenerator<List<String>, AddNames> {
static String get header => '/// Added names.';
static String get footer => '/// This is the footer.';
@override
List<String> generateStreamItemForAnnotatedElement(
Element element,
ConstantReader annotation,
BuildStep buildStep,
) {
final result = <String>[];
if (element is ClassElement) {
final nameObjects = element.getField('names')?.computeConstantValue()?.toListValue();
for (final nameObj in nameObjects ?? []) {
result.add(nameObj.toStringValue());
}
return result;
}
return <String>['Could not read name'];
}
@override
FutureOr<String> generateMergedContent(Stream<List<String>> stream) async {
final b = StringBuffer();
var i = 0;
final allNames = <List<String>>[];
await for (final names in stream) {
b.write('final name$i = [');
b.writelnAllQ(names, separator2: ',');
b.writeln('];');
++i;
allNames.add(names);
}
b.writeln('');
b.writeln('final List<List<String>> names = [');
for (var names in allNames) {
b.writeln(' [');
b.writelnAllQ(names, separator2: ',');
b.writeln(' ],');
}
b.writeln('];');
return b.toString();
}
}
3. 创建MergingBuilder
实例
通常将生成器放置在一个名为builder.dart
的文件中,位于生成器包的lib
文件夹中。
import 'package:build/build.dart';
import 'package:merging_builder/merging_builder.dart';
import 'src/generators/add_names_generator.dart';
import 'src/generators/assistant_generator.dart';
Builder addNamesBuilder(BuilderOptions options) {
BuilderOptions defaultOptions = BuilderOptions({
'input_files': 'lib/*.dart',
'output_file': 'lib/output.dart',
'header': AddNamesGenerator.header,
'footer': AddNamesGenerator.footer,
'sort_assets': true,
});
options = defaultOptions.overrideWith(options);
return MergingBuilder<List<String>, LibDir>(
generator: AddNamesGenerator(),
inputFiles: options.config['input_files'],
outputFile: options.config['output_file'],
header: options.config['header'],
footer: options.config['footer'],
sortAssets: options.config['sort_assets'],
);
}
Builder assistantBuilder(BuilderOptions options) {
BuilderOptions defaultOptions = BuilderOptions({
'input_files': 'lib/*.dart',
'output_files': 'lib/output/assistant_(*).dart',
'header': AssistantGenerator.header,
'footer': AssistantGenerator.footer,
'root': ''
});
options = defaultOptions.overrideWith(options);
return StandaloneBuilder<LibDir>(
generator: AssistantGenerator(),
inputFiles: options.config['input_files'],
outputFiles: options.config['output_files'],
root: options.config['root']);
}
4. 配置生成器
在定义生成器的包中添加生成器配置。
builders:
add_names_builder:
import: "package:researcher_builder/builder.dart"
builder_factories: ["addNamesBuilder"]
build_extensions: {"lib/$lib$": ["lib/output.dart"]}
auto_apply: root_package
build_to: source
assistant_builder:
import: "package:researcher_builder/builder.dart"
builder_factories: ["assistantBuilder"]
build_extensions: {"lib/$lib$": ["*.dart"]}
auto_apply: root_package
build_to: source
5. 在使用生成器的包中配置build.yaml
targets:
$default:
builders:
researcher_builder|add_names_builder:
enabled: true
options:
input_files: 'lib/input/*.dart'
output_file: 'lib/output/researchers.dart'
sort_assets: false
header: '// Header specified in build.yaml.'
footer: '// Footer specified in build.yaml.'
researcher_builder|assistant_builder:
enabled: true
options:
input_files: 'lib/input/*.dart'
output_files: 'lib/output/assistant_(*).dart'
root: ''
6. 添加依赖项到使用生成器的包
在使用生成器的包的pubspec.yaml
文件中添加researcher_builder
和build_runner
作为开发依赖项。
name: researcher
description: Example demonstrating how to use the library merging_builder.
environment:
sdk: '>=2.17.0 <3.0.0'
dev_dependencies:
build_runner: ^1.10.0
researcher_builder:
path: ../researcher_builder
7. 启动构建过程
运行以下命令启动构建过程:
dart run build_runner build --delete-conflicting-outputs --verbose
示例项目结构
以下是示例项目的完整结构:
example/
├── researcher/
│ ├── lib/
│ │ └── input/
│ │ ├── researcher_a.dart
│ │ └── researcher_b.dart
│ └── pubspec.yaml
└── researcher_builder/
├── lib/
│ ├── builder.dart
│ └── generators/
│ ├── add_names_generator.dart
│ └── assistant_generator.dart
└── pubspec.yaml
更多关于Flutter插件功能集成插件merging_builder的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
1 回复