Flutter打包与配置管理插件get_packer的使用

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

Flutter打包与配置管理插件GetPacker的使用

GetPacker简介

GetPacker 是一个高性能的 Dart 序列化库,旨在高效地打包和解包数据结构。它提供了一个快速且紧凑的替代方案,相较于 JSON 编码/解码和 MessagePack,GetPacker 没有任何限制(例如支持 DateTime 对象)。

特性

  • 快速编码和解码:支持多种数据类型的高效编码和解码。
  • 紧凑的二进制格式:相比 JSON,生成的数据量更小。
  • 支持多种数据类型
    • null
    • 布尔值
    • 整数(包括大整数)
    • 浮点数
    • 字符串
    • 二进制数据 (Uint8List)
    • 列表
    • 映射
    • DateTime
    • BigInt
  • 易于使用的 API:简单易用的接口。
  • 自定义对象支持:通过 PackedModel 混入类轻松实现自定义对象的序列化和反序列化。

安装

pubspec.yaml 文件中添加以下依赖:

dependencies:
  get_packer: ^1.0.0

然后运行 dart pub getflutter pub get(如果你使用的是 Flutter)。

使用方法

基本用法

以下是一个简单的示例,展示了如何使用 GetPacker 进行数据的编码和解码:

import 'package:get_packer/get_packer.dart';

void main() {
  // 编码
  final data = {
    'name': 'John Doe',
    'age': 30,
    'isStudent': false,
    'grades': [85, 90, 92],
  };

  final encoded = GetPacker.pack(data);
  print(encoded); // 输出: [132, 164, 110, 97, 109, 101, 168, 74, 111, 104, 110, 32, 68, 111, 101, 163, 97, 103, 101, 30, 169, 105, 115, 83, 116, 117, 100, 101, 110, 116, 194, 166, 103, 114, 97, 100, 101, 115, 147, 85, 90, 92]

  // 解码
  final decoded = GetPacker.unpack(encoded);

  print(decoded); // 输出: {name: John Doe, age: 30, isStudent: false, grades: [85, 90, 92]}
}

使用自定义对象

你可以使用 PackedModel 混入类来轻松实现自定义对象的序列化和反序列化:

class User with PackedModel {
  String name;
  int age;

  User(this.name, this.age);

  [@override](/user/override)
  Map<String, dynamic> toJson() => {'name': name, 'age': age};

  [@override](/user/override)
  static User fromJson(Map<String, dynamic> json) {
    return User(json['name'], json['age']);
  }
}

void main() {
  final user = User('Alice', 25);

  // 打包
  final packed = user.pack();

  // 解包
  final unpackedUser = User.fromJson(GetPacker.unpack(packed));

  print('${unpackedUser.name}, ${unpackedUser.age}'); // 输出: Alice, 25
}

性能

GetPacker 设计为快速且高效。在基准测试中,它通常比标准的 JSON 编码/解码在速度和大小上表现更好:

// 示例基准测试结果:
JSON Encode(RunTime): 191.99949000407997 us.
GetPacker Encode(RunTime): 140.41056438954482 us.

Size comparison:
JSON size: 1268 bytes
GetPacker size: 986 bytes
GetPacker is 22.24% smaller

如果你想自行测试,以下是用于基准测试的代码:

import 'dart:convert';
import 'dart:typed_data';

import 'package:benchmark_harness/benchmark_harness.dart';
import 'package:get_packer/get_packer.dart';

final testData = {
  'nullValue': null,
  'boolean': true,
  'integer': 42,
  'negativeInteger': -42,
  'double': 3.14159,
  'string': 'Hello, World!',
  'binary': Uint8List.fromList([1, 2, 3, 4, 5, 6, 7, 8]),
  'array': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
  'map': {'key1': 'value1', 'key2': 'value2', 'key3': 'value3'},
  'nestedArray': [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
  ],
  'nestedMap': {
    'outer1': {'inner1': 'value1', 'inner2': 'value2'},
    'outer2': {'inner3': 'value3', 'inner4': 'value4'}
  },
  'mixedArray': [
    1,
    'two',
    3.0,
    true,
    null,
    {'key': 'value'}
  ],
  'complexObject': {
    'id': 1001,
    'name': 'Complex Object',
    'attributes': ['attr1', 'attr2', 'attr3'],
    'metadata': {
      'created': '2023-09-30T12:00:00Z',
      'updated': '2023-09-30T14:30:00Z',
      'tags': ['tag1', 'tag2', 'tag3']
    }
  },
  'longString':
      'This is a much longer string that contains multiple sentences. '
          'It can be used to test how the system handles larger text inputs. '
          'The string can contain various characters and punctuation marks!',
  'largeInteger': 1234567890123456789,
  'negativeDouble': -273.15,
  'emptyStructures': {'emptyArray': [], 'emptyMap': {}, 'emptyString': ''},
  'deeplyNestedStructure': {
    'level1': {
      'level2': {
        'level3': {
          'level4': {'level5': 'Deep value'}
        }
      }
    }
  },
  'repeatingData': List.generate(
      5,
      (index) =>
          {'id': index, 'name': 'Item ${index + 1}', 'isEven': index % 2 == 0}),
};

class JsonEncodeBenchmark extends BenchmarkBase {
  JsonEncodeBenchmark() : super('JSON Encode');

  [@override](/user/override)
  void run() {
    final foo = jsonEncode(testData);
    jsonDecode(foo);
  }
}

class GetPackerEncodeBenchmark extends BenchmarkBase {
  GetPackerEncodeBenchmark() : super('GetPacker Encode');

  [@override](/user/override)
  void run() {
    final foo = GetPacker.pack(testData);
    GetPacker.unpack(foo);
  }
}

void main() {
  JsonEncodeBenchmark().report();
  GetPackerEncodeBenchmark().report();

  // 多次运行以获得更准确的结果
  print('\nRunning multiple iterations:');
  for (int i = 0; i < 5; i++) {
    print('\nIteration ${i + 1}:');
    JsonEncodeBenchmark().report();
    GetPackerEncodeBenchmark().report();
  }

  // 比较大小
  final jsonSize = utf8.encode(jsonEncode(testData)).length;
  final getPackerSize = GetPacker.pack(testData).length;

  print('\nSize comparison:');
  print('JSON size: $jsonSize bytes');
  print('GetPacker size: $getPackerSize bytes');
  print('Size difference: ${(jsonSize - getPackerSize)} bytes');
  print(
      'GetPacker is ${((jsonSize - getPackerSize) / jsonSize * 100).toStringAsFixed(2)}% smaller');
}

更多关于Flutter打包与配置管理插件get_packer的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter打包与配置管理插件get_packer的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在Flutter项目中,打包与配置管理是一个非常重要的环节,get_packer 是一个能够帮助你自动化这个过程的有用工具。虽然 get_packer 不是一个官方插件,但假设它是一个类似功能的自定义工具,我们可以模拟其使用方式。不过,由于具体的 get_packer 插件细节可能有所不同,这里我会给出一个通用的 Flutter 打包和配置管理的示例,并假设 get_packer 插件提供了类似的功能。

首先,确保你的 Flutter 项目已经设置好,并且你有基本的 Flutter 开发环境。

1. 安装依赖

假设 get_packer 是一个 Flutter 插件,你需要在 pubspec.yaml 文件中添加它:

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

然后运行 flutter pub get 来安装依赖。

2. 配置 get_packer

由于 get_packer 的具体配置可能有所不同,这里假设它允许你通过 yaml 文件来配置不同的打包选项。创建一个 packer_config.yaml 文件:

# packer_config.yaml
android:
  flavorDimensions: "version"
  productFlavors:
    free:
      applicationIdSuffix: ".free"
      versionNameSuffix: "-free"
    paid:
      applicationIdSuffix: ".paid"
      versionNameSuffix: "-paid"
ios:
  configurations:
    Debug:
      scheme: RunnerDebug
    Release:
      scheme: Runner

3. 使用 get_packer 进行打包

假设 get_packer 提供了一个命令行工具来根据配置进行打包,你可以在项目的根目录下创建一个脚本来自动化这个过程。例如,创建一个 build.sh 脚本(对于 macOS/Linux)或 build.bat 脚本(对于 Windows):

build.sh 示例(macOS/Linux)

#!/bin/bash

# 切换到 Flutter 项目根目录
cd "$(dirname "$0")/.."

# 清理之前的构建
flutter clean

# 遍历所有配置并打包
for flavor in "free" "paid"; do
  echo "Building Android $flavor flavor..."
  flutter build apk --flavor $flavor -t lib/main_$flavor.dart
  
  echo "Building iOS $flavor configuration..."
  flutter build ios --release --flavor $flavor -t lib/main_$flavor.dart
done

注意:这里假设你为每个 flavor 创建了不同的入口文件 main_free.dartmain_paid.dart

build.bat 示例(Windows)

@echo off

:: 切换到 Flutter 项目根目录
cd /d "%~dp0.."

:: 清理之前的构建
flutter clean

:: 遍历所有配置并打包
for %%f in (free paid) do (
    echo Building Android %%f flavor...
    flutter build apk --flavor %%f -t lib\main_%%f.dart
    
    echo Building iOS %%f configuration...
    flutter build ios --release --flavor %%f -t lib\main_%%f.dart
)

4. 运行打包脚本

在 macOS/Linux 上,给 build.sh 添加执行权限并运行:

chmod +x build.sh
./build.sh

在 Windows 上,双击 build.bat 或在命令行中运行它。

注意事项

  • 实际的 get_packer 插件可能有不同的配置方式和命令行接口,请参考其官方文档。
  • Flutter 的 flavor 和 configuration 支持允许你为不同的市场或用户群体创建不同的构建版本。
  • 确保你的 Flutter 环境已经正确配置,包括 Android SDK 和 iOS 开发工具。

由于 get_packer 并非一个广泛认知的插件,上述示例基于假设和通用实践。如果你使用的是具体的 get_packer 插件,请参考其官方文档和示例代码。

回到顶部