Flutter辅助工具或功能增强插件mint的使用

发布于 1周前 作者 ionicwang 最后一次编辑是 5天前 来自 Flutter

Flutter辅助工具或功能增强插件mint的使用

警告:此插件仍处于实验阶段。

Mint 提供了一个通过模板生成代码的框架。它自带了对 copyWithcopyJarequalitytoJsonfromJson 的支持。然而,它允许你生成任何你想要的东西,并以你希望的方式与生成的代码进行交互。所有生成的代码都来自模板,你可以轻松地修改这些模板以满足你的需求。这种能力延伸到与生成的第三方代码的交互。这使得你的类不需要任何“钩子”来集成生成的代码。Mint 的目标是干净、简单且直观的数据类。

使用方法

使用 Mint 非常简单:

pubspec.yaml 中添加依赖
dependencies:
  au: ^0.2.1
  json_annotation: ^4.7.0

dev_dependencies:
  build_runner: ^2.0.0
  json_serializable: ^6.3.1
  mint: ^0.6.1
将其添加到模型中
// 导入 au 注解
import 'package:au/au.dart';
// 导入其他可能需要的库
import 'package:json_annotation/json_annotation.dart';

// 包含生成的代码。注意扩展名为 .au.dart 而不是 .g.dart。
part 'generated/person.au.dart';

// 使用 Au 注解标记类
@Au()
// 添加其他可能需要的注解
@JsonSerializable(explicitToJson: true)
// 包含 _$Person 混入(模式为 _$CLASS)
class Person with _$Person {
  final String name;
  final int age;

  const Person(this.name, this.age);

  // 从生成的代码中复制构造函数
  // 位置参数表示字段名按字母顺序排列
  const Person._fromAu(
    this.age,
    this.name,
  );
}
更新 build.yaml

确保在项目的根目录下的 build.yaml 文件中有以下配置。更多细节见配置部分:

targets:
  $default:
    builders:
      mint:mint_builder:
        enabled: True
        options:
          templates:
            abstract: "package:mint/src/templates/abstract.mustache"
            child: "package:mint/src/templates/child.mustache"
            from_au_hint: "package:mint/src/templates/from_au_hint.mustache"
            jar: "package:mint/src/templates/jar.mustache"
            mixin: "package:mint/src/templates/mixin.mustache"
            from_json: "package:mint/src/templates/from_json.mustache"
            to_json: "package:mint/src/templates/to_json.mustache"
          mixin_annotations:
            - annotation: 'JsonSerializable'
              template: 'to_json'
          child_annotations:
            - annotation: 'JsonSerializable'
              template: 'from_json'
      source_gen:combining_builder:
        enabled: False
      mint:mint_combining_builder:
        enabled: True
        options:
          build_extensions: 
            '{{path}}/{{name}}.dart': '{{path}}/generated/{{name}}.au.dart' 
          mint_rewire_parts:
            - 'json_serializable.g.part'
运行构建器

运行构建器以生成代码(或者使用 watch 选项在保存时自动执行):

dart run build_runner build --delete-conflicting-outputs

或者:

dart run build_runner watch --delete-conflicting-outputs

或者对于 Flutter:

flutter packages pub run build_runner build --delete-conflicting-outputs
复制 _fromAu 构造函数(如果未手动编写)

在生成的代码顶部,你应该找到 au 构造函数代码:

// 复制 _fromAu 构造函数到基类。
// const Person._fromAu(this.age,this.name,);
完成
  final p1 = const Person('John', 35);

  final p2 = p1.copyWith(
    age: const AuValue<int>(25),
  );

  assert(p1 != p2);

  // 或者只是复制 jar
  final p3 = p1.copyJar(const AuPersonJar(
    age: 21,
    name: 'Joe',
  ));

  final p4 = AuPerson.fromJson(p3.toJson());

  assert(p3 == p4);

  final p5 = const AuPerson('John', 35);
  assert(p5 == p1);

注意,你不再需要为这些常见功能编写代码。你也不再需要添加 fromJson 工厂构造函数,可以使用生成的 AuPerson 子类的 fromJson 工厂。这是因为 PersonAuPerson 实例是等效的。

重新生成

唯一需要重新运行构建器的情况是你修改了模型中的字段或构造函数定义。如前所述,这可以通过 watch 命令自动完成:dart run build_runner watch --delete-conflicting-outputs

如果你想更进一步,可以设置 VSCode 任务配置,以便在打开项目时自动运行此命令。只需在 .vscode 目录内添加以下 tasks.json

{
	"version": "2.0.0",
	"tasks": [
		{
			"type": "flutter",
			"command": "flutter",
            "args": [
                "pub",
                "run",
                "build_runner",
                "watch",
                "lib/", 
                "--delete-conflicting-outputs",
            ],
			"problemMatcher": [
				"$dart-build_runner"
			],
			"options": {
				"cwd": "example",
			},
			"runOptions": {
        "runOn": "folderOpen"
      },
			"presentation": {
				"echo": true,
				"reveal": "always",
				"focus": false,
				"panel": "dedicated",
				"showReuseMessage": false,
				"clear": false
			},
			"group": "build",
			"label": "Flutter Build Runner",
			"detail": "example"
		}
	]
}

配置

代码生成的配置通过 build.yaml 文件完成:

targets:
  $default:
    builders:
      mint:mint_builder:
        enabled: True
        options:
          templates:
            # 必需的模板
            abstract: "package:mint/src/templates/abstract.mustache"
            child: "package:mint/src/templates/child.mustache"
            from_au_hint: "package:mint/src/templates/from_au_hint.mustache"
            jar: "package:mint/src/templates/jar.mustache"
            mixin: "package:mint/src/templates/mixin.mustache"
            # 注解模板
            from_json: "package:mint/src/templates/from_json.mustache"
            to_json: "package:mint/src/templates/to_json.mustache"
          mixin_annotations:
            - annotation: 'JsonSerializable'
              template: 'to_json'
          child_annotations:
            - annotation: 'JsonSerializable'
              template: 'from_json'
      # 禁用 source_gen combining_builder 以提高性能
      source_gen:combining_builder:
        enabled: False
      # 利用 mint:combining_builder 代替
      mint:mint_combining_builder:
        enabled: True
        options:
          # 允许你将文件生成到自己的 /generated 目录中。
          build_extensions: 
            '{{path}}/{{name}}.dart': '{{path}}/generated/{{name}}.au.dart' 
          # 哪些部分将生成模型引用替换为 Au 子类引用(Person > AuPerson)。当存在工厂创建时,这仅在 child_annotations 中需要。这基本上会重写生成的代码,使其看起来像是为子类而不是模型生成的。这样你可以在其他生成的代码中与其交互,而无需向模型添加任何内容。
          mint_rewire_parts:
            - 'json_serializable.g.part'

第一步是定义模板映射。必需的键是:abstractchildfrom_au_hintjarmixin。键表示每个模板的标识符,值是 Mustache 模板文件的 URI。如果你要使用自己的模板,只需将相应的 URI 替换为你项目中的一个。

还支持注解模板(这是 Mint 如何提供 JsonSerializable 支持的方式)。它还可以用于创建基于注解的自动生成。一旦定义了模板,我们只需提供 mixin_annotationschild_annotations 的相应模板标识符列表。

例如:如果类被注解为 JsonSerializable,则在混入中生成 to_json 模板。同样,如果我们需要向子类添加一些功能(例如,工厂构造函数),我们只需使用 child_annotations 列表即可。

注意:如你所见,配置的注解是字符串而不是实际的 TypeInterfaces。如果你有多个同名的注解类,这可能会带来挑战。

注意:你可能不希望在代码库中引用生成的 Au* 类。如果是这种情况,你可以选择只使用混入,这仍然会给你大部分功能:copyWith、copyJar、equality、toJson 等。当然,你需要在模型中定义必要的工厂(fromJson)。唯一其他的变化是禁用 mint_combining_builder,启用 source_gen 一个。

模板参数

当你为注解创建自己的模板时,你将需要访问一些模型元数据。这可以通过以下变量实现:

[
  'model_class_name',
  'model_abstract_class_name',
  'model_child_class_name',
  'model_jar_class_name',
  'fields': [
    'field_name',
    'field_name_capitalized',
    'field_type',
    'field_type_with_nullability',
    'field_is_nullable',
    'field_is_private',
    'field_is_last',
  ]
]

以下是 abstract.mustache 文件的一个示例,该文件创建了一个具有与模型相同字段的抽象类:

abstract class {{model_abstract_class_name}} extends AuMinted {
    {{#fields}}
    {{field_type_with_nullability}} get {{field_name}};
    {{/fields}}
}

自定义模板针对注解

在示例项目中,你可以看到如何设置它。这非常简单。

创建你的注解

在 Dart 中,任何类都可以是一个注解,只要它有一个 const 构造函数。

class Foo {
  const Foo();
}
创建你的自定义模板
// 从 Foo 注解生成的自定义函数
String foo() {
    return 'foo on {{model_class_name}} - {{#fields}}{{field_name}}{{^field_is_last}},{{/field_is_last}}{{/fields}}';
}
更新 build.yaml
  templates:
    abstract: "package:mint/src/templates/abstract.mustache"
    child: "package:mint/src/templates/child.mustache"
    from_au_hint: "package:mint/src/templates/from_au_hint.mustache"
    jar: "package:mint/src/templates/jar.mustache"
    mixin: "package:mint/src/templates/mixin.mustache"
    from_json: "package:mint/src/templates/from_json.mustache"
    to_json: "package:mint/src/templates/to_json.mustache"
    # 添加你的自定义模板
    with_foo: "package:example/templates/with_foo.mustache"
  mixin_annotations:
    - annotation: 'JsonSerializable'
      template: 'to_json'
    # 添加你的自定义注解,并将其配置为添加到 mixin_annotations
    - annotation: 'Foo'
      template: 'with_foo'
使用它
@Au()
@Foo()
@JsonSerializable(explicitToJson: true)
class WithFoo with _$WithFoo {
  final String name;
  final int age;

  const WithFoo(this.name, this.age);

  const WithFoo._fromAu(
    this.age,
    this.name,
  );
}

由于模型被注解为 Foo,并且我们配置了 Foo 生成模板 with_foo,系统将在方法中生成此附加函数:

  // 从 Foo 注解生成的自定义函数
  String foo() {
    return 'foo on WithFoo - age,name';
  }

你现在可以像其他任何方法一样使用它:

final w = WithFoo('foo', 99);
print(w.foo());

工厂构造函数

工厂构造函数不能作为混入的一部分定义。因此,Mint 还生成一个原始模型的子类。此子类命名为 Au(CLASS)。此子类负责为我们与生成的代码进行交互。它允许我们不必定义 fromJson 或其他类似工厂构造函数,这些可能是由第三方代码生成器所需。你可以以与父模型相同的方式利用子类。

如果你希望代码成为子类的一部分,只需将 Foo 注解配置移动到 child_annotations 部分:

  child_annotations:
    - annotation: 'JsonSerializable'
      template: 'from_json'
    # 添加 Foo 注解配置
    - annotation: 'Foo'
      template: 'with_foo'
可选重写

根据你要集成的第三方代码生成库,你也可能需要“重写”第三方生成的代码,使其现在指向子类而不是最初生成的模型(Person > AuPerson)。要实现这一点,只需将部分文件扩展添加到 mint_combining_builder 配置中:

      mint:mint_combining_builder:
        enabled: True
        options:
          mint_rewire_parts:
            - 'json_serializable.g.part'
            # 添加需要重写的部分

更多关于Flutter辅助工具或功能增强插件mint的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter辅助工具或功能增强插件mint的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在Flutter中,插件通常用于扩展应用程序的功能,但由于“mint”插件的具体功能未定义,我们将基于插件名称和一般用途进行一些合理的假设,并编写一些假设性的代码示例。这些示例并不代表“mint”插件的实际功能,而是用于展示如何在Flutter项目中使用一个假设的插件。

假设功能:性能监控与优化

假设“mint”插件是一个用于性能监控和优化的工具,它可能提供CPU、内存使用情况的监控,以及应用启动时间的测量等功能。以下是如何在Flutter项目中使用这样一个假设性插件的示例代码。

1. 添加依赖

首先,在pubspec.yaml文件中添加对“mint”插件的依赖(注意:由于这是一个假设的插件,所以实际的依赖名称和版本是不存在的):

dependencies:
  flutter:
    sdk: flutter
  mint: ^0.0.1  # 假设的版本号

2. 导入插件

在你的Dart文件中导入插件:

import 'package:mint/mint.dart';

3. 初始化插件

在应用程序的入口点(通常是main.dart)初始化插件:

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  
  // 假设 Mint 有一个全局的初始化方法
  Mint.initialize();

  runApp(MyApp());
}

4. 使用插件功能

假设“mint”插件提供了监控CPU、内存使用情况和测量应用启动时间的功能,我们可以这样使用它们:

import 'package:flutter/material.dart';
import 'package:mint/mint.dart';

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  Mint.initialize();

  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Mint Plugin Demo'),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Text('CPU Usage: ${_getCpuUsage()}%'),
              Text('Memory Usage: ${_getMemoryUsage()} MB'),
              Text('App Startup Time: ${_getAppStartupTime()} ms'),
            ],
          ),
        ),
      ),
    );
  }

  // 假设方法,用于获取CPU使用率
  String _getCpuUsage() {
    // 这里应该是 Mint 插件提供的 API 调用
    // 例如:return Mint.cpuUsage.toStringAsFixed(2);
    // 由于这是假设,我们返回一个静态值
    return 'N/A'; // 假设值
  }

  // 假设方法,用于获取内存使用量
  String _getMemoryUsage() {
    // 例如:return Mint.memoryUsage.toString();
    return 'N/A'; // 假设值
  }

  // 假设方法,用于获取应用启动时间
  String _getAppStartupTime() {
    // 假设 Mint 插件在应用启动时记录了时间
    // 例如:return (DateTime.now().difference(Mint.startupTime).inMilliseconds).toString();
    return 'N/A'; // 假设值
  }
}

注意

  • 以上代码是基于对“mint”插件功能的假设编写的,并不代表实际插件的API。
  • 在实际使用中,你需要参考插件的官方文档来了解其具体的API和使用方法。
  • 由于“mint”插件是假设的,所以上述代码中的方法调用(如Mint.cpuUsageMint.memoryUsageMint.startupTime)在实际中是不存在的,你需要根据插件的实际API进行调整。
回到顶部