Flutter数据不可变集合插件freezed_collection的使用

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

Flutter数据不可变集合插件freezed_collection的使用

freezed_collection 是一个扩展 freezed 的库,它提供了深度集合的 copyWith 功能。通过该库,你可以更方便地操作不可变的数据结构。

特性

  • ✅ FreezedList<T>.fromJson
  • ✅ FreezedList<T>.copyWith.replaceFirst(T newElement, bool Function(T element) what)

示例

import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:freezed_collection/freezed_collection.dart';

part 'one.freezed.dart';

@freezed
class One with _$One {
  const factory One(String name, Two two) = _One;

  // 从JSON解析
  factory One.fromJson(Map<String, dynamic> json) => _$OneFromJson(json);
}

@freezed
class Two with _$Two {
  const factory Two(String name, FreezedList<Three> threes) = _Two;

  // 从JSON解析
  factory Two.fromJson(Map<String, dynamic> json) => _$TwoFromJson(json);
}

@freezed
class Three with _$Three {
  const factory Three(String name) = _Three;

  // 从JSON解析
  factory Three.fromJson(Map<String, dynamic> json) => _$ThreeFromJson(json);
}

void test() {
  // 初始化数据
  final var1 = One('1', Two('2', FreezedList([Three('31'), Three('32'), Three('33')])));
  final var2 = One('1', Two('2', FreezedList([Three('31'), Three('32'), Three('33')])));
  final var21 = var2.copyWith();

  // 比较var1与var2及var21
  expect(var1, equals(var2));
  expect(var1, equals(var21));

  // 修改var21中的某些值
  final var3 = var21.copyWith
      .two(name: '21')
      .copyWith
      .two
      .threes
      .replaceFirst(Three('XXX'), (element) => element.name == '31');

  // 验证修改后的结果
  expect(var3, isNot(var21));

  // 进一步修改var3
  final var4 = var3.copyWith
      .two(name: '2')
      .copyWith
      .two
      .threes
      .replaceFirst(Three('31'), (element) => element.name == 'XXX');

  // 验证最终结果
  expect(var4, equals(var21));
}

示例代码

import 'package:freezed_collection/freezed_collection.dart';

import 'dart:convert';

import 'assistant.dart';
import 'company.dart';
import 'director.dart';

// 打印公司信息
void printT<T>(T company) => print(json.encode(company));

void main() {
  // 初始化公司对象
  final company = Company(
      name: '1',
      director: Director(
          name: 'director1',
          assistants: FreezedList(
              [Assistant(age: 1, name: '1'), Assistant(age: 3, name: '3')])));

  // 将公司对象转换为JSON字符串,并重新解析
  final jsonString = json.encode(company);
  final restoredCompany = Company.fromJson(json.decode(jsonString));

  // 打印恢复后的公司信息
  print(restoredCompany);

  // 创建新的公司对象,替换第一个年龄为1的助手
  Company? newCompany = company.copyWith.director.assistants.replaceFirstWhere(
    Assistant(age: 2, name: '2'),
    (element) => element.age == 1,
  );

  // 创建另一个新的公司对象,替换第一个年龄为2的助手
  Company? newCompany2 =
      newCompany.copyWith.director.assistants.replaceFirstWhere(
    Assistant(age: 1, name: '1'),
    (element) => element.age == 2,
  );

  // 打印原始公司、新公司及其进一步修改后的公司
  printT(company);
  printT(newCompany);
  printT(newCompany2);

  // 验证新公司是否等于原始公司
  print('Is newCompany equal to company? ${newCompany == company}');
  print('Is newCompany equal to company? ${newCompany2 == company}');
}

更多关于Flutter数据不可变集合插件freezed_collection的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter数据不可变集合插件freezed_collection的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,下面是一个关于如何在Flutter项目中使用freezed_collection插件来处理不可变集合的示例代码。freezed_collection插件基于freezed库,为Flutter开发者提供了不可变的List、Set和Map。

步骤 1: 添加依赖

首先,在你的pubspec.yaml文件中添加freezedfreezed_annotation依赖:

dependencies:
  flutter:
    sdk: flutter
  freezed_annotation: ^x.x.x  # 使用最新版本号

dev_dependencies:
  build_runner: ^x.x.x  # 使用最新版本号
  freezed: ^x.x.x      # 使用最新版本号

步骤 2: 创建数据模型

接下来,创建一个数据模型并使用freezed库来生成不可变类。同时,使用freezed_collection来处理不可变的集合。

import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:freezed_collection/freezed_collection.dart';

part 'model.freezed.dart';

@freezed
class User with _$User {
  const factory User({
    required String name,
    required int age,
    required List<String> hobbies,
    required Set<String> skills,
    required Map<String, String> addresses,
  }) = _User;

  factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
}

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

flutter pub run build_runner build

步骤 3: 使用不可变集合

现在,你可以在你的Flutter应用中使用这个不可变的数据模型。以下是一个简单的示例,展示如何创建和修改一个User对象:

void main() {
  // 创建一个User对象
  final user = User(
    name: 'Alice',
    age: 30,
    hobbies: ['Reading', 'Hiking'],
    skills: {'Dart', 'Flutter'},
    addresses: {'Home': '123 Main St', 'Office': '456 Elm St'},
  );

  // 由于集合是不可变的,我们需要创建一个新的User对象来“修改”它
  final updatedUser = user.copyWith(
    hobbies: user.hobbies..add('Cycling'),  // 注意:这里不能直接修改,只是演示意图
    // 正确的方式是创建一个新的List
    hobbies: [...user.hobbies, 'Cycling'],
    skills: user.skills.union({'React'}).toSet(),
    addresses: {
      ...user.addresses,
      'Work': '789 Oak St',
    },
  );

  // 打印原始用户和更新后的用户
  print('Original User: $user');
  print('Updated User: $updatedUser');

  // 尝试直接修改会失败(编译时错误)
  // user.hobbies.add('Swimming'); // 这行会报错,因为集合是不可变的
}

注意:在上面的代码中,尽管copyWith方法被用来创建一个新的User对象,但直接修改集合(如user.hobbies.add('Cycling'))是错误的,这里只是为了说明意图。正确的方式是使用不可变集合的操作,如[...user.hobbies, 'Cycling']来创建一个新的List。

结论

通过使用freezedfreezed_collection插件,你可以轻松地在Flutter应用中实现不可变的数据模型,从而提高应用的状态管理效率和可靠性。上述代码示例展示了如何定义和使用这些不可变集合,希望对你有所帮助。

回到顶部