Menu
CoddyTech

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 中构建事件驱动类至关重要,例如在数据变化时通知应用中的多个部分、处理用户操作,或管理对象中的实时更新。

challenge icon

挑战

简单

让我们构建一个消息中心系统,让多个订阅者能够实时接收消息!你将使用 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: 关闭消息中心
}
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

面向对象编程中的所有课

自己练习: Dart 在线编译器