Dart 语言 Stream操作符与聚合模式实践

Dart阿木 发布于 2025-06-18 6 次阅读


Dart 语言 Stream 操作符与聚合模式实践

在 Dart 语言中,Stream 是一种异步数据流,它允许我们以异步的方式处理数据。Stream 操作符和聚合模式是 Dart 中处理 Stream 数据的两种重要技术。本文将围绕这两个主题,通过一系列的实践代码,深入探讨 Dart 中 Stream 的使用和聚合模式的应用。

Stream 操作符

Stream 操作符是 Dart 中用于处理 Stream 数据的一系列函数。这些操作符可以连接多个 Stream,对数据进行转换、过滤、聚合等操作。

1. 创建 Stream

在 Dart 中,我们可以使用 `StreamController` 来创建一个 Stream。

dart

StreamController<String> controller = StreamController<String>();

// 添加数据到 Stream


controller.add('Hello');


controller.add('World');

// 关闭 Stream


controller.close();


2. Stream 操作符

Dart 提供了丰富的 Stream 操作符,以下是一些常用的操作符:

2.1 `map`

`map` 操作符用于转换 Stream 中的数据。

dart

Stream<String> stream = controller.stream;


Stream<String> mappedStream = stream.map((event) => event.toUpperCase());


2.2 `where`

`where` 操作符用于过滤 Stream 中的数据。

dart

Stream<String> filteredStream = stream.where((event) => event.length > 3);


2.3 `fold`

`fold` 操作符用于聚合 Stream 中的数据。

dart

Stream<int> foldedStream = stream.fold(0, (previousValue, element) => previousValue + element.length);


2.4 `asyncExpand`

`asyncExpand` 操作符用于异步地转换 Stream 中的数据。

dart

Stream<String> asyncStream = Stream.fromIterable(['Hello', 'World']);


Stream<String> expandedStream = asyncStream.asyncExpand((event) async {


await Future.delayed(Duration(seconds: 1));


return [event, 'Async'];


});


聚合模式

聚合模式是一种设计模式,它允许我们将多个操作符组合在一起,形成一个数据处理流水线。这种模式在 Dart 中通过 Stream 操作符来实现。

1. 简单聚合

以下是一个简单的聚合示例,它将 Stream 中的数据转换为大写,然后过滤出长度大于 3 的字符串。

dart

Stream<String> stream = controller.stream;


Stream<String> aggregatedStream = stream


.map((event) => event.toUpperCase())


.where((event) => event.length > 3);


2. 复杂聚合

在复杂的情况下,我们可以使用多个操作符来构建一个复杂的聚合流水线。

dart

Stream<String> complexStream = stream


.map((event) => event.toUpperCase())


.where((event) => event.length > 3)


.asyncExpand((event) async {


await Future.delayed(Duration(seconds: 1));


return [event, 'Async'];


})


.fold([], (previousValue, element) => [...previousValue, element]);


在这个例子中,我们首先将 Stream 中的数据转换为大写,然后过滤出长度大于 3 的字符串。接着,我们使用 `asyncExpand` 来异步地添加额外的数据,最后使用 `fold` 来聚合所有数据到一个列表中。

实践案例

以下是一个使用 Stream 操作符和聚合模式来处理异步数据的实践案例。

1. 异步获取用户数据

假设我们需要从服务器异步获取用户数据,并对其进行处理。

dart

Stream<String> fetchUserData() async {


// 模拟异步获取数据


await Future.delayed(Duration(seconds: 2));


yield 'John Doe';


await Future.delayed(Duration(seconds: 2));


yield 'Jane Smith';


}

Stream<String> processUserData() async {


Stream<String> userDataStream = fetchUserData();


Stream<String> processedStream = userDataStream


.map((event) => event.toUpperCase())


.where((event) => event.length > 3);


yield processedStream;


}


在这个例子中,`fetchUserData` 是一个异步生成器函数,它模拟从服务器获取用户数据的过程。`processUserData` 函数使用 Stream 操作符来处理这些数据。

2. 使用 StreamBuilder 构建界面

在 Flutter 应用中,我们可以使用 `StreamBuilder` 来构建依赖于 Stream 数据的界面。

dart

StreamBuilder<String>(


stream: processUserData(),


builder: (context, snapshot) {


if (snapshot.connectionState == ConnectionState.waiting) {


return CircularProgressIndicator();


} else if (snapshot.hasError) {


return Text('Error: ${snapshot.error}');


} else {


return Text('Processed User: ${snapshot.data}');


}


},


)


在这个例子中,`StreamBuilder` 会根据 `processUserData` Stream 的状态来构建界面。当 Stream 处理数据时,界面会显示一个进度指示器;当数据处理完成时,界面会显示处理后的用户数据。

总结

Stream 操作符和聚合模式是 Dart 中处理异步数据流的重要工具。通过使用 Stream 操作符,我们可以轻松地对 Stream 数据进行转换、过滤和聚合。聚合模式则允许我们将多个操作符组合在一起,形成一个数据处理流水线。通过本文的实践案例,我们可以看到如何使用这些技术来处理异步数据和构建动态界面。