写点什么

Dart _ 什么是 Stream,安卓开发不得不会

用户头像
Android架构
关注
发布于: 刚刚

?? StreamController

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


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


//创建一条处理 int 类型的流 StreamController<int> numController = StreamController();numController.sink.add(123);


泛型定义了我们能向流上推送什么类型


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


的数据。它可以是任何类型!


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


StreamController controller = StreamController();


//监听这个流的出口,当有 data 流出时,打印这个 dataStreamSubscription 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<int> 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<int> controller = StreamController<int>();


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);


输出: Bad state: Stream has already been listened to. 单订阅流不能有多个收听者。

"Broadcast" streams

广播流允许任意数量的收听者,且无论是否有收听者,他都能产生事件。所以中途进来的收听者将不会收到之前的消息。


如果多个收听者想要收听单个订阅流,请使用 asBroadcastStream 在非广播流之上创建广播流。


如果在触发事件时将收听者添加到广播流,则该侦听器将不会接收当前正在触发的事件。如果取消收听,收听者会立即停止接收事件。


一般的流都是单订阅流。从 Stream 继承的广播流必须重写 isBroadcast 才能返回 true。


StreamController controller = StreamController();//将单订阅流转化为广播流 Stream stream = controller.stream.asBroadcastStream();


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

用户头像

Android架构

关注

还未添加个人签名 2021.10.31 加入

还未添加个人简介

评论

发布
暂无评论
Dart _ 什么是Stream,安卓开发不得不会