Flutter二进制序列化插件binary_serializable_generator的使用

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

Flutter二进制序列化插件binary_serializable_generator的使用

binary_serializable_generator

binary_serializable_generator 是一个用于生成 binary_serializable 插件中 BinaryType 的代码生成工具。


安装

首先,安装 binary_serializable 作为常规依赖项,并将 binary_serializable_generatorbuild_runner 作为开发依赖项:

$ dart pub add binary_serializable
$ dart pub add -d binary_serializable_generator build_runner

使用

导入 package:binary_serializable/binary_serializable.dart 并为类添加 [@BinarySerializable](/user/BinarySerializable)() 注解以生成对应的 BinaryType。字段上可以使用 BinaryType 的子类型来实现序列化。

示例代码

import 'package:binary_serializable/binary_serializable.dart';

part 'example.g.dart'; // 替换为实际文件名.g.dart,build_runner 将在此文件中生成代码

[@BinarySerializable](/user/BinarySerializable)()
class Example {
  @uint64
  final int id;

  [@utf8String](/user/utf8String)
  final String name;

  @LengthPrefixedListType(uint8, utf8String)
  final List<String> tags;

  Example(this.id, this.name, this.tags);
}

运行以下命令以生成代码:

$ dart run build_runner build

生成的代码将出现在 file_name.g.dart 中:

class ExampleType extends BinaryType<Example> {
  const ExampleType();

  [@override](/user/override)
  Uint8List encode(Example input) {
    final builder = BytesBuilder(copy: false);
    builder.add(uint64.encode(input.id)); // 序列化 id
    builder.add(utf8String.encode(input.name)); // 序列化 name
    builder.add(const LengthPrefixedListType(
      uint8,
      utf8String,
    ).encode(input.tags)); // 序列化 tags
    return builder.takeBytes();
  }

  [@override](/user/override)
  BinaryConversion<Example> startConversion(void Function(Example) onValue) =>
      _ExampleConversion(
        this,
        onValue,
      );
}

class _ExampleConversion extends CompositeBinaryConversion<Example> {
  _ExampleConversion(
    this.type,
    super.onValue,
  );

  final ExampleType type;

  [@override](/user/override)
  BinaryConversion startConversion() {
    return uint64.startConversion((id) { // 开始解析 id
      currentConversion = utf8String.startConversion((name) { // 解析 name
        currentConversion = const LengthPrefixedListType(
          uint8,
          utf8String,
        ).startConversion((tags) { // 解析 tags
          final instance = Example(
            id,
            name,
            tags,
          );
          onValue(instance); // 调用回调函数
        });
      });
    });
  }
}

高级用法

自定义构造函数

如果类有多个构造函数,可以通过在构造函数上添加 [@BinarySerializable](/user/BinarySerializable)() 注解来指定要使用的构造函数。需要注意以下限制:

  1. 构造函数的每个参数都必须有一个字段,该字段带有与参数同名的 BinaryType 注解。
  2. 类中所有带 BinaryType 注解的字段都会按顺序被序列化,无论它们是否出现在构造函数中。

示例代码

[@BinarySerializable](/user/BinarySerializable)(constructor: 'fromMap')
class Example {
  @uint64
  final int id;

  [@utf8String](/user/utf8String)
  final String name;

  @LengthPrefixedListType(uint8, utf8String)
  final List<String> tags;

  Example(this.id, this.name, this.tags);

  factory Example.fromMap(Map<String, dynamic> map) {
    return Example(
      map['id'] as int,
      map['name'] as String,
      (map['tags'] as List<dynamic>).cast<String>(),
    );
  }
}

运行 dart run build_runner build 后,会生成相应的代码。


带泛型的类

如果类包含泛型,则可以在生成的 BinaryType 中指定这些泛型的类型。

示例代码

[@BinarySerializable](/user/BinarySerializable)()
class GenericType<T, U> {
  @Generic('T')
  final T genericField;

  @LengthPrefixedListType(uint8, Generic('U'))
  final List<U> genericList;

  GenericType(this.genericField, this.genericList);
}

class GenericTypeType<T, U> extends BinaryType<GenericType<T, U>> {
  const GenericTypeType(
    this.genericTypeU,
    this.genericTypeT,
  );

  final BinaryType<U> genericTypeU;

  final BinaryType<T> genericTypeT;

  [@override](/user/override)
  Uint8List encode(GenericType<T, U> input) {
    final builder = BytesBuilder(copy: false);
    builder.add(genericTypeT.encode(input.genericField)); // 序列化 genericField
    builder.add(LengthPrefixedListType(
      uint8,
      genericTypeU,
    ).encode(input.genericList)); // 序列化 genericList
    return builder.takeBytes();
  }

  [@override](/user/override)
  BinaryConversion<GenericType<T, U>> startConversion(
          void Function(GenericType<T, U>) onValue) =>
      _GenericTypeConversion(
        this,
        onValue,
      );
}

class _GenericTypeConversion<T, U>
    extends CompositeBinaryConversion<GenericType<T, U>> {
  _GenericTypeConversion(
    this.type,
    super.onValue,
  );

  final GenericTypeType<T, U> type;

  [@override](/user/override)
  BinaryConversion startConversion() {
    return type.genericTypeT.startConversion((genericField) {
      currentConversion = LengthPrefixedListType(
        uint8,
        type.genericTypeU,
      ).startConversion((genericList) {
        final instance = GenericType<T, U>(
          genericField,
          genericList,
        );
        onValue(instance);
      });
    });
  }
}

抽象类

对于抽象类,可以使用 MultiBinaryType 来生成对应的 BinaryType

示例代码

[@BinarySerializable](/user/BinarySerializable)()
abstract class Message {
  [@uint8](/user/uint8)
  int get id;
}

[@BinarySerializable](/user/BinarySerializable)()
class StringMessage extends Message {
  [@override](/user/override)
  int get id => 2;

  [@utf8String](/user/utf8String)
  final String data;

  StringMessage(this.data);
}

[@BinarySerializable](/user/BinarySerializable)()
class IntegerMessage extends Message {
  [@override](/user/override)
  int get id => 1;

  [@int64](/user/int64)
  final int data;

  IntegerMessage(this.data);
}

class MessageType extends MultiBinaryType<Message, int> {
  const MessageType([super.subtypes = MessageType.defaultSubtypes]);

  static const Map<int, BinaryType<Message>> defaultSubtypes = {
    2: StringMessageType(),
    1: IntegerMessageType(),
  };

  [@override](/user/override)
  int extractPrelude(Message instance) => instance.id;

  [@override](/user/override)
  BinaryConversion<int> startPreludeConversion(void Function(int) onValue) =>
      _MessagePreludeConversion(
        this,
        onValue,
      );
}

class _MessagePreludeConversion extends CompositeBinaryConversion<int> {
  _MessagePreludeConversion(
    this.type,
    super.onValue,
  );

  final MessageType type;

  [@override](/user/override)
  BinaryConversion startConversion() {
    return uint8.startConversion((id) {
      onValue(id);
    });
  }
}

更多关于Flutter二进制序列化插件binary_serializable_generator的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter二进制序列化插件binary_serializable_generator的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


binary_serializable_generator 是一个用于 Flutter 的代码生成插件,它可以帮助你生成二进制序列化和反序列化的代码。该插件通常与 binary_serializable 包一起使用,以便在 Flutter 应用中高效地处理二进制数据。

以下是使用 binary_serializable_generator 的步骤:

1. 添加依赖

首先,你需要在 pubspec.yaml 文件中添加 binary_serializablebinary_serializable_generator 依赖。binary_serializable 是运行时依赖,而 binary_serializable_generator 是开发时依赖。

dependencies:
  binary_serializable: ^1.0.0

dev_dependencies:
  build_runner: ^2.0.0
  binary_serializable_generator: ^1.0.0

2. 创建数据模型

接下来,你需要创建一个数据模型类,并使用 @BinarySerializable() 注解标记该类。这个注解告诉 binary_serializable_generator 需要为这个类生成序列化和反序列化的代码。

import 'package:binary_serializable/binary_serializable.dart';

part 'example.g.dart';

@BinarySerializable()
class Example {
  final int id;
  final String name;

  Example(this.id, this.name);

  // 生成的文件中会自动包含 `toBinary` 和 `fromBinary` 方法
}

3. 生成代码

使用 build_runner 生成序列化和反序列化的代码。在终端中运行以下命令:

flutter pub run build_runner build

这将生成一个 example.g.dart 文件,其中包含 Example 类的 toBinaryfromBinary 方法。

4. 使用生成的代码

现在你可以使用生成的 toBinaryfromBinary 方法来序列化和反序列化 Example 对象。

void main() {
  final example = Example(1, "Test");

  // 序列化
  final binaryData = example.toBinary();

  // 反序列化
  final deserializedExample = Example.fromBinary(binaryData);

  print(deserializedExample.id);    // 输出: 1
  print(deserializedExample.name);  // 输出: Test
}

5. 处理复杂对象

如果你的类中包含其他复杂对象,确保这些对象也使用 @BinarySerializable() 注解,并且也生成了相应的 toBinaryfromBinary 方法。

6. 清理生成的文件

如果你不再需要生成的文件,可以使用以下命令清理它们:

flutter pub run build_runner clean
回到顶部
AI 助手
你好,我是IT营的 AI 助手
您可以尝试点击下方的快捷入口开启体验!