欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net

在这里插入图片描述

前言

在 Flutter 开发中,State Management (状态管理) 的核心原则通常是 Immutability (不可变性)。
如果我们直接修改 ListMap 的内容,FrameWork 可能检测不到变化,导致 UI 不刷新。或者,因为引用传递(Reference Passing)导致多个组件共享同一个 Mutable List,产生难以追踪的副作用 Bug。

Dart 标准库的 List.unmodifiable 虽然能创建不可变列表,但每次修改都需要全量拷贝(toList()),性能开销大(O(N))。

built_collection 是 Google 维护的一个高性能不可变集合库(它是 built_value生态的一部分)。它采用了 Builder 模式,允许你以看似 Mutable 的方式构建集合,最后生成高效的 Immutable 实例。

对于 OpenHarmony 应用,特别是在处理大量数据列表(如长列表、复杂图表数据)时,使用 built_collection 能显著降低 GC 压力,提升渲染帧率。

一、核心原理

built_collection 包含 BuiltList, BuiltSet, BuiltMap 等类型。
它们的核心思想是:写时拷贝 (Check-on-write)构建器模式

  1. Immutable: BuiltList 实例一旦创建,内容绝不可变。
  2. Builder: 通过 .toBuilder() 获取一个可变的 ListBuilder,由于它基于底层实现优化,在未调用 .build() 前不会频繁触发全量复制。
  3. Efficient: 内部使用了 Trie (前缀树) 或 Hash Array Mapped Trie (HAMT) 等结构(虽然 Dart 版主要是优化了 Copy-on-write),比简单的 List.from 快得多。

toBuilder()

remove(0)

build()

BuiltList

ListBuilder

新 BuiltList

二、集成与用法详解

2.1 添加依赖

dependencies:
  built_collection: ^5.1.1

2.2 基础用法

import 'package:built_collection/built_collection.dart';

void main() {
  // 1. 创建不可变列表
  final list1 = BuiltList<int>([1, 2, 3]);

  // list1.add(4); // 编译错误!没有 add 方法

  // 2. 修改并生成新列表
  final list2 = list1.rebuild((b) => b
    ..add(4)
    ..addAll([5, 6])
    ..remove(1));

  print(list1); // [1, 2, 3] (原列表未变)
  print(list2); // [2, 3, 4, 5, 6]
}

在这里插入图片描述

2.3 配合 Bloc/Redux

在状态管理中,我们需要生成新的 State。

class AppState {
  final BuiltList<String> todos;
  AppState(this.todos);
}

// Reducer
AppState reducer(AppState state, dynamic action) {
  if (action is AddTodo) {
    // 极其简洁的更新语法
    return AppState(state.todos.rebuild((b) => b.add(action.text)));
  }
  return state;
}

三、OpenHarmony 适配与实战:高性能列表渲染

在 OpenHarmony 设备上渲染长列表(ListView)时,Flutter 的 Diff 算法会比较新旧 Widget 的属性。如果属性是 List,因为不仅比较引用的开销O(1),如果引用不同还要比较内容的开销O(N),这可能导致掉帧。

但是,如果你使用 BuiltList

  1. == 比较极快:两个 BuiltList 如果底层数据没变,它们的 hashCode 是缓存的,且 == 操作符经过深度优化(如果引用相同直接返回 true)。
  2. 防止意外修改:你再也不会遇到“我在子组件理清空了 List,结果父组件的数据也没了”这种 Bug。
class TodoList extends StatelessWidget {
  // 使用 BuiltList 而不是 List
  final BuiltList<String> items;

  const TodoList({Key? key, required this.items}) : super(key: key);

  
  Widget build(BuildContext context) {
    return ListView.builder(
      itemCount: items.length,
      itemBuilder: (context, index) {
        return ListTile(title: Text(items[index]));
      },
    );
  }
}

3.1 序列化 (JSON)

虽然 built_collection 不直接提供 JSON 支持,但它通常配合 built_valuejson_serializable 使用。
需要编写自定义 Converter。

// json_serializable 配置
class BuiltListConverter implements JsonConverter<BuiltList<dynamic>, List<dynamic>> {
  const BuiltListConverter();

  
  BuiltList<dynamic> fromJson(List<dynamic> json) => BuiltList<dynamic>(json);

  
  List<dynamic> toJson(BuiltList<dynamic> object) => object.toList();
}

四、功能详解:深度集合 (Nested Collections)

处理嵌套数据结构(如 Map<String, List<int>>)通常很痛苦。

// 标准 Dart: 修改深层数据需要多层拷贝
var newMap = Map<String, List<int>>.from(oldMap);
newMap['key'] = List<int>.from(newMap['key']!)..add(1);

使用 built_collection

final map = BuiltMap<String, BuiltList<int>>({'nums': BuiltList([1, 2])});

final newMap = map.rebuild((b) => b
  ..['nums'] = (b['nums']!.toBuilder()..add(3)).build()
);
// 虽然看起来稍微繁琐,但它是线程安全且高效的

在这里插入图片描述

五、总结

built_collection 是追求极致性能和代码安全性的开发者的首选。它强迫你使用 Builder 模式来修改数据,虽然多写了几行代码,但换来的是零副作用极高的运行时效率

对于 OpenHarmony 开发者:

  • 内存优化:在内存受限的 IoT 设备上,避免不必要的 List 拷贝能节省大量 RAM。
  • 架构清晰:它是 Redux/Bloc 架构的最佳拍档,让状态流转清晰可见。

最佳实践

  1. API 边界:在 Service/Repository 层的返回值中使用 BuiltList,明确告诉调用者:这个数据是只读的,不要尝试修改它。
  2. 避免滥用:在局部的小逻辑(如一个临时 for 循环处理)中,普通的 List 足够了。只在跨组件传递状态时使用 BuiltList

六、完整实战示例

import 'package:built_collection/built_collection.dart';

void main() {
  print('=== 基础 List 操作 ===');
  // 1. 创建不可变列表
  final list = BuiltList<int>([1, 2, 3]);
  
  // 2. 修改:必须通过 rebuild,它返回新对象
  final newList = list.rebuild((b) => b
      ..add(4)
      ..remove(1)
  );

  print('原始列表: $list');     // [1, 2, 3]
  print('新列表:   $newList'); // [2, 3, 4]

  print('\n=== 深度嵌套修改 ===');
  // 3. 嵌套结构的痛点解决
  final map = BuiltMap<String, BuiltList<int>>({
    '奇数': BuiltList([1, 3]),
    '偶数': BuiltList([2, 4]),
  });

  // 需求:给 '奇数' 列表里添加一个 5
  final updatedMap = map.rebuild((b) => b
    ..updateValue('奇数', (listBuilder) => listBuilder..add(5))
  );

  print('原始 Map: $map'); 
  // {奇数: [1, 3], 偶数: [2, 4]}
  
  print('更新后 Map: $updatedMap'); 
  // {奇数: [1, 3, 5], 偶数: [2, 4]}
}

在这里插入图片描述

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐