您好!
我试图了解Dart中溪流的运作方式 这是一个简单的例子:
我们有Publisher
class Publisher {
StreamController<String> _publishCtrl = new StreamController<String>();
Stream<String> onPublish;
Publisher() {
onPublish = _publishCtrl.stream.asBroadcastStream();
}
void publish(String s) {
_publishCtrl.add(s);
}
}
Reader
class Reader {
String name;
Reader(this.name);
read(String s) {
print("My name is $name. I read string '$s'");
}
}
简单函数main()
:
main() {
Publisher publisher = new Publisher();
Reader john = new Reader('John');
Reader smith = new Reader('Smith');
publisher.onPublish.listen(john.read);
publisher.onPublish.listen(smith.read);
for (var i = 0; i < 5; i++) {
publisher.publish("Test message $i");
}
}
作为代码的结果,我从阅读器John
获得5条控制台消息,从阅读器Smith
获得5条消息。
My name is John. I read string 'Test message 0'
My name is Smith. I read string 'Test message 0'
My name is John. I read string 'Test message 1'
My name is Smith. I read string 'Test message 1'
My name is John. I read string 'Test message 2'
My name is Smith. I read string 'Test message 2'
My name is John. I read string 'Test message 3'
My name is Smith. I read string 'Test message 3'
My name is John. I read string 'Test message 4'
My name is Smith. I read string 'Test message 4'
一切正常。但是,如果我尝试更改周期for
,那么在2步读取Smith
阻止接收消息之后,该消息将只接收读者John
。
以下是更改函数main ()
的示例:
main() {
Publisher publisher = new Publisher();
Reader john = new Reader('John');
Reader smith = new Reader('Smith');
publisher.onPublish.listen(john.read);
var smithSub = publisher.onPublish.listen(smith.read);
for (var i = 0; i < 5; i++) {
publisher.publish("Test message $i");
if (i > 2) {
smithSub.cancel();
}
}
}
如果您运行此代码,则控制台只会通过 John :
发布My name is John. I read string 'Test message 0'
My name is John. I read string 'Test message 1'
My name is John. I read string 'Test message 2'
My name is John. I read string 'Test message 3'
My name is John. I read string 'Test message 4'
但我认为应该有来自读者史密斯的3条消息。
如果我知道的话,请告诉我吗?如果没有,请帮助我,理解为什么会发生这种情况。
非常感谢。
答案 0 :(得分:3)
创建同步StreamController
StreamController<String> _publishCtrl = new StreamController<String>(sync: true);
或允许控制器在发送新项目之前处理这些项目
int i = 0;
Future.doWhile(() {
i++;
publisher.publish("Test message $i");
if (i > 2) {
subscriptions
..forEach((s) => s.cancel())
..clear();
}
return i < 5;
}