Stream 控制器
本课属于 Coddy Dart 学习旅程的“面向对象编程”单元。第 78 课,共 110 课。
虽然 async* 生成器很适合用预定义的数据创建流,但有时你需要更多控制,比如从代码的不同部分向流中添加数据。这时就可以使用 StreamController。
StreamController 充当流的管理器。它为你提供一个“接收端”来添加数据,以及一个供监听器订阅的“流”:
import 'dart:async';
void main() {
var controller = StreamController<String>();
// 监听数据流
controller.stream.listen((data) {
print('Received: $data');
});
// 通过 sink 添加数据
controller.add('Hello');
controller.add('World');
controller.close(); // 完成后务必关闭
}add() 方法会将新值推送到流中,所有监听器都会立即收到这些值。完成后,你应始终调用 close() 来释放资源。
默认情况下,一个流只能有一个监听器。要添加多个监听器,请使用广播控制器:
import 'dart:async';
void main() {
var controller = StreamController<int>.broadcast();
controller.stream.listen((n) => print('Listener 1: $n'));
controller.stream.listen((n) => print('Listener 2: $n'));
controller.add(42);
controller.close();
}StreamControllers 对于在 OOP 中构建事件驱动类至关重要,例如在数据变化时通知应用中的多个部分、处理用户操作,或管理对象中的实时更新。
挑战
简单让我们构建一个消息中心系统,让多个订阅者能够实时接收消息!你将使用 StreamController 管理消息流,并演示广播流如何让多个监听器接收消息。
你将把代码分成两个文件:
message_hub.dart:创建一个使用 StreamController 管理消息分发的MessageHub类。你的消息中心应当:- 在内部使用广播型
StreamController<String>,这样多个监听器都可以订阅 - 提供一个名为
messages的 getter,返回供监听器订阅的流 - 包含一个
broadcast(String message)方法,用于向流中添加消息 - 包含一个
shutdown()方法,用于关闭控制器
- 在内部使用广播型
main.dart:导入你的消息中心,并设置一个有多个订阅者监听同一条流的场景:- 创建一个
MessageHub实例 - 添加第一个监听器,按以下格式打印消息:
Subscriber A: [message] - 添加第二个监听器,按以下格式打印消息:
Subscriber B: [message] - 广播三条消息:
Hello everyone、Welcome to the hub和Goodbye - 关闭消息中心
- 创建一个
记得在消息中心文件中导入 dart:async,以使用 StreamController。注意,每条广播消息都会被两个订阅者接收,这就是广播流的强大之处!
预期输出:
Subscriber A: Hello everyone
Subscriber B: Hello everyone
Subscriber A: Welcome to the hub
Subscriber B: Welcome to the hub
Subscriber A: Goodbye
Subscriber B: Goodbye亲手试试
import 'message_hub.dart';
void main() {
// TODO: 创建一个 MessageHub 实例
// TODO: 添加第一个监听器,打印:Subscriber A: [message]
// TODO: 添加第二个监听器,打印:Subscriber B: [message]
// TODO: 广播三条消息:
// - "Hello everyone"
// - "Welcome to the hub"
// - "Goodbye"
// TODO: 关闭消息中心
}
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: Dart 在线编译器