Dart _ 什么是Stream,看完直呼内行

本文深入探讨了Dart中的Stream,包括如何通过构造函数、StreamController、async*生成Stream,以及如何监听和处理Stream。此外,文章还介绍了Stream的种类,如单订阅流,并提供了丰富的代码示例帮助理解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


获得 Stream 的方法:

  • 通过构造函数
  • 使用StreamController
  • IO Stream

stream有三个构造方法:

  • Stream.fromFuture:从Future创建新的单订阅流,当future完成时将触发一个data或者error,然后使用Down事件关闭这个流。

  • Stream.fromFutures:从一组Future创建一个单订阅流,每个future都有自己的data或者error事件,当整个Futures完成后,流将会关闭。如果Futures为空,流将会立刻关闭。

  • Stream.fromIterable:创建从一个集合中获取其数据的单订阅流。

Stream.fromIntreable([1,2,3]);

🧐监听 Stream 的方法

监听一个流最常见的方法就是listen。当有事件发出时,流将会通知listener。Listen方法提供了这几种触发事件:

  • onData(必填):收到数据时触发
  • onError:收到Error时触发
  • onDone:结束时触发
  • unsubscribeOnError:遇到第一个Error时是否取消订阅,默认为false

使用 await for 处理 Stream

除了通过 listen,我们还可以使用 await for 来处理。

Future sumStream(Stream stream) async {
var sum = 0;
await for (var value in stream) {
sum += value;
}
return sum;
}

这段代码将会接收一个 Stream 然后统计所有事件之和,然后返回结果。await for 能够在每个事件到来的时候处理它。我们知道,一个 stream 它接收事件的时机是不确定的,那什么时候应该退出 await for 循环呢?答案是,当这个 Stream 完成或关闭的时候。

你可以复制这段代码到 DartPad 里面多做几次试验。

😏 StreamController

如果你想创建一条新的流的话,非常简单!😀 使用StreamController,它为你提供了非常丰富的功能,你能够在streamController上发送数据,处理错误,并获得结果!

//任意类型的流
StreamController controller = StreamController();
controller.sink.add(123);
controller.sink.add(“xyz”);
controller.sink.add(Anything);

//创建一条处理int类型的流
StreamC

《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》

【docs.qq.com/doc/DSkNLaERkbnFoS0ZF】 完整内容开源分享

ontroller numController = StreamController();
numController.sink.add(123);

泛型定义了我们能向流上推送什么类型的数据。它可以是任何类型!

我们再来看看如何获取最后的结果。

StreamController controller = StreamController();

//监听这个流的出口,当有data流出时,打印这个data
StreamSubscription subscription =
controller.stream.listen((data)=>print("$data"));

controller.sink.add(123);

输出: 123

你需要将一个方法交给stream的listen函数,这个方法入参(data)是我们的StreamController处理完毕后产生的结果,我们监听出口,并获得了这个结果(data)。这里可以使用lambda表达式,也可以是其他任何函数。

(这里我为了方便区分,把listen说成函数,(data)=>print(data)说成方法,其实是一个东西。)

通过 async* 生成 stream

如果我们有一系列事件需要处理,我们也许会需要把它转化为 stream。这时候可以使用 async - yield* 来生成一个 Stream。

Stream countStream(int to) async* {
for (int i = 1; i <= to; i++) {
yield i;
}
}

当循环退出时,这个 Stream 也就 done 了。我们可以结合之前说的 await for 更加深刻的体验一下。

你可以在 这里 直接运行我的样例代码。

🤠Transforming an existing stream

假如你已经有了一个流,你可以通过它转化成为一条新的流。非常简单!流提供了map(),where(),expand(),和take()方法,能够轻松将已有的流转化为新的流。

where

如果你想要筛选掉一些不想要的事件。例如一个猜数游戏,用户可以输入数字,当输入正确的时候,我们做出一定反应。而我们必须筛选掉所有错误的答案,这个时候我们可以使用where筛选掉不需要的数字。

stream.where((event){…})

where函数接收一个事件,每当这个流有东西流到where函数的时候,这就是那个事件。我们或许根本不需要这个事件,但是必须作为参数传入。

take

如果你想要控制这个流最多能传多少个东西。比如输入密码,我们可能想让用户最多输四次,那么我们可以使用take来限制。

stream.take(4);

take函数接收一个int,代表最多能经过take函数的事件次数。当传输次数达到这个数字时,这个流将会关闭,无法再传输。

transform

如果你需要更多的控制转换,那么请使用transform()方法。他需要配合StreamTransformer进行使用。我们先来看下面一段猜数游戏,然后我会向你解释。

StreamController controller = StreamController();

final transformer = StreamTransformer<int,String>.fromHandlers(
handleData:(value, sink){
if(value==100){
sink.add(“你猜对了”);
}
else{ sink.addError(‘还没猜中,再试一次吧’);
}
});

controller.stream
.transform(transformer)
.listen(
(data) => print(data),
onError:(err) => print(err));

controller.sink.add(23);
//controller.sink.add(100);

输出: 还没猜中,再试一次吧

StreamTransformer<S,T>是我们stream的检查员,他负责接收stream通过的信息,然后进行处理返回一条新的流。

  • S代表之前的流的输入类型,我们这里是输入一个数字,所以是int。
  • T代表转化后流的输入类型,我们这里add进去的是一串字符串,所以是String。
  • handleData接收一个value并创建一条新的流并暴露sink,我们可以在这里对流进行转化。
  • 我们还可以addError进去告诉后面有问题。

然后我们监听transform之后的流,当转换好的event流出时,我们打印这个event,这个event就是我们刚才add进sink的数据。onError能够捕捉到我们add进去的err。

🤨Stream的种类

流有两种

  • “Single-subscription” streams 单订阅流
  • “broadcast” streams 多订阅流

“Single-subscription” streams

单个订阅流在流的整个生命周期内仅允许有一个listener。它在有收听者之前不会生成事件,并且在取消收听时它会停止发送事件,即使你仍然在Sink.add更多事件。

即使在第一个订阅被取消后,也不允许在单个订阅流上进行两次侦听。

单订阅流通常用于流式传输更大的连续数据块,如文件I / O.

StreamController controller = StreamController();

controller.stream.listen((data)=> print(data));
controller.stream.listen((data)=> print(data));

controller.sink.add(123);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值