Flutter模型生成插件im_model_gen的使用

发布于 1周前 作者 yuanlaile 来自 Flutter

Flutter 模型生成插件 im_model_gen 的使用

这个库提供了用于不可变模型的代码生成,包括值比较 ==copyWith 方法。

项目目标:

  • 标准语法。
  • 在运行时之前捕获错误。
  • 低源代码生成,你的IDE会很高兴。
  • 改善输出二进制文件大小。
  • 解锁继承(虽然鼓励每天使用组合,但“是-一个”模式也不错)。
  • 不太侵入性。

要求

Dart SDK >= 3.6.0

使用

@ImModel 注解你的类

import 'package:im_model/im_model.dart';

part 'example.g.dart'; // 声明生成的部分文件

@ImModel()
class Example with _$ExampleMixin { // 关联你的类与生成的混入类
  final String id;
  final String? name;
  final ImList<int> values; // ImList 是这个包的一部分。

  const Example(this.id, {this.name, required this.values});
}

使用生成的类

const example = Example(id: 'id', values: ImList.empty());

// 复制
example.copyWith(text: 'test'); // Example(id: "id", text: test, values; [])
example.copyWith(text: null); // Example(id: "id", text: null, values: [])

// 相等性
const exampleTwo = Example(id: 'id', values: ImList.empty());
example == exampleTwo; // true
example == exampleTwo.copyWith(values: [1]); // false

// 不可变性
// example.values.add(1); // 'add' 未定义。

代码生成命令

dart run build_runner build --delete-conflicting-outputs

特性更多内容

有两个可用的注解。

@ImModel 可以应用于类,并具有以下参数:

  • ignoreCopy: 允许忽略复制生成。默认为 false
  • ignoreEqual: 允许忽略相等性生成。默认为 false
  • copyConstructor: 如果需要,你可以设置一个命名构造函数用于复制生成。默认为 null

@ImModel 可以应用于类字段以覆盖类注解,并具有以下参数:

  • ignoreCopy: 允许忽略复制生成。默认为 null
  • ignoreEqual: 允许忽略相等性生成。默认为 null

集合

这个包通过简单地包装核心集合来提供不可变/可比较/可哈希的集合。

你必须将所有可变集合前缀为其不可变的对应物。

  • List => ImList
  • Map => ImMap
  • Set => ImSet

代码生成器会在检测到可变集合时提供错误消息。

为了方便集合的修改,有两个获取器:

  • mut => 获取集合的可变版本。你可以免费使用它,只有当你修改它时才会复制该集合。
  • immut => 获取集合的不可变版本。

查看下面的示例进行演示。

⚠️

  • 显然,像其他地方一样,集合是不可变的,前提是元素也是不可变的。
  • 目前,如果你使用自定义集合实现,该包将无法检测到。因此,像 MyFooList<int>ImList<MyFooList<int>> 这样的类型会被允许,但 ImList<Set<int>> 或其他变体不会。

相等性

此包使用 Dart 3 记录使 ImModel 可比较。

此外,ImModel 强制同类型的模型之间的相等性。

现在,像 MyImModel() == Object() 这样的事情将在编译时触发错误。

最后,性能完全由 Dart 内部库确定,部分由 Im* 集合确定。

更高级的使用

现在我们已经了解了所有内容,这是一个完整的(花哨的)示例:

/// 类上的反转忽略标志 => 由字段覆盖
/// [id] 不是 `copyWith` 的一部分。
/// 只有 [id] 是相等性的部分。
@ImModel(ignoreEqual: true, ignoreCopy: true)
class Parent<T> with _$ParentMixin<T> {
  @ImField(ignoreEqual: false)
  final String id;
  @ImField(ignoreCopy: false)
  final T? aValue;

  const Parent(this.id, this.aValue);
}

/// [collection] 类成员是不可变的(你不能使用 add、remove 等)。
/// [id] 不是 `copyWith` 的一部分。
/// 只有 [id] 和 [collection] 是相等性的部分。
@ImModel()
class Child<T> extends Parent<T> with _$ChildMixin<T> {
  final ImList<int> collection;

  const Child(super.id, super.aValue, {required this.collection});
}
void main() {
  var obj1 = Child('a', 0, collection: [1].immut);
  var obj2 = Child('a', 0, collection: ImList([1]));
  // obj1 == obj2 => true

  obj1 = obj1.copyWith(collection: obj1.collection.mut..add(2));
  // obj1 == obj2 => false

  // 注意两点:
  // - 我们使用 `mut` 获取器来修改初始集合以获得更简洁的语法。
  // - 我们不必再次包装集合使其成为不可变的,这是在生成的代码中完成的。

  // obj1.copyWith(id: 'b');
  // 名为 'id' 的命名参数未定义。
}

更多关于Flutter模型生成插件im_model_gen的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter模型生成插件im_model_gen的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是一个关于如何在Flutter项目中使用im_model_gen插件的示例代码案例。im_model_gen插件通常用于自动生成代码,特别是与即时通讯(IM)相关的数据模型。请注意,由于im_model_gen并非一个广为人知的官方或广泛使用的Flutter插件,以下示例基于假设其工作原理类似于其他代码生成插件,如json_serializable

1. 添加依赖

首先,你需要在pubspec.yaml文件中添加im_model_gen依赖。假设该插件存在,且其配置如下:

dependencies:
  flutter:
    sdk: flutter
  im_model_gen: ^x.y.z  # 替换为实际版本号

dev_dependencies:
  build_runner: ^x.y.z  # 代码生成工具,通常需要最新版本

运行flutter pub get来安装依赖。

2. 定义数据模型

创建一个数据模型文件,例如message_model.dart,并定义你想要生成代码的类。假设im_model_gen使用特定的注解来标记需要生成代码的类,类似于json_serializable@JsonSerializable()注解。

import 'package:im_model_gen/im_model_gen.dart';

part 'message_model.g.dart';  // 生成的文件

@IMModel()  // 假设这是im_model_gen的注解
class Message {
  final String sender;
  final String receiver;
  final String content;
  final DateTime timestamp;

  Message({
    required this.sender,
    required this.receiver,
    required this.content,
    required this.timestamp,
  });

  // 通常,代码生成插件会生成fromJson和toJson方法
  // 在这里,我们假设im_model_gen也会这样做
  factory Message.fromJson(Map<String, dynamic> json) => _$MessageFromJson(json);
  Map<String, dynamic> toJson() => _$MessageToJson(this);
}

3. 运行代码生成

在终端中运行以下命令来生成代码:

flutter pub run build_runner build

这将在你的项目目录下生成一个message_model.g.dart文件,其中包含Message类的fromJsontoJson方法的实现。

4. 使用生成的代码

现在你可以在你的Flutter应用中使用生成的代码了。例如,从JSON数据创建Message对象,或者将Message对象转换为JSON。

void main() {
  // 示例JSON数据
  String jsonData = '''
  {
    "sender": "Alice",
    "receiver": "Bob",
    "content": "Hello, Bob!",
    "timestamp": "2023-10-05T14:48:00.000Z"
  }
  ''';

  // 将JSON数据解析为Message对象
  Map<String, dynamic> jsonMap = jsonDecode(jsonData);
  Message message = Message.fromJson(jsonMap);

  // 打印Message对象的属性
  print('Sender: ${message.sender}');
  print('Receiver: ${message.receiver}');
  print('Content: ${message.content}');
  print('Timestamp: ${message.timestamp}');

  // 将Message对象转换为JSON
  Map<String, dynamic> jsonOutput = message.toJson();
  print('JSON Output: $jsonOutput');
}

注意

  • 由于im_model_gen并非一个已知的广泛使用的插件,上述代码和注解(如@IMModel())是基于假设的。实际使用时,你需要查阅im_model_gen的官方文档来了解其具体的用法和注解。
  • 如果im_model_gen插件不存在或功能不同,你可能需要寻找其他类似功能的插件,或者手动实现数据模型的序列化和反序列化。
回到顶部