开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第3天,点击查看活动详情
前言
在Dart中,与Java等其他语言最大的不同应该要数Stream和 Future,这俩都是Dart:async库的核心API,对异步提供了非常好的支持。这篇文章我们先首要深入浅出一下 Stream。
正文
1.概括
Stream,中文名为“流”。也正如其名,这正是一个流操作,数据从源头来,经过处理,又流出去。这与Android开发中,Kotlin的Flow,RxJava等等有着相同的理念。在大后端也经常用到这个概念,如比较出名的Flink框架,其实就是一个处理流的框架。
用一个图概括:
graph TD
入口 --> Stream对象
Stream对象 --> 出口
问题来了,那如何往入口里塞东西呢?塞了之后Stream操作了什么呢?操作完之后又给了出口,那整体不就相当于是一个观察者模式?
首先,我们先回答一下,其实整个Stream是可以理解成一个观察者模式的,出口一旦有东西出来,相关的订阅者就会收到信息,进而对出来的数据进行处理。
而后,我们来实际操作一下如何塞数据,如何处理数据,如何从出口获得数据。
2.操作与使用
首先我们需要创建一个Stream类的对象。构造方法有5种:
Stream.fromFuture,从Future创建新的单订阅流,当future完成时将触发一个data或者error,然后使用Down事件关闭这个流。Stream.fromFutures,从一组Future创建一个单订阅流,每个future都有自己的data或者error事件,当整个Futures完成后,流将会关闭。如果Futures为空,流将会立刻关闭。Stream.fromIterable,创建从一个集合中获取其数据的单订阅流。- 直接使用
StreamController,其中已经包含一个Stream对象。调用StreamController.stream即可。 - 通过生成器创建流。
async*标记的方法称为异步生成器,在其中可以通过yield生成单个元素,yield*生成多个元素,最终汇集成流。
限于篇幅,我们本次着重介绍第四种使用方法。
创建Controller。
var _controller = StreamController<List<Passage>>.broadcast();
随后,获得入口passageSink。
passageSink = _controller!.sink as StreamSink<List<Passage>>;
往入口丢数据
passageSink!.add(result);
获得Stream对象
stream = _controller!.stream as Stream<List<Passage>>;
要消费这个Stream的话,就有很多种方法了,
我们这里使用StreamBuilder进行消费。
...
StreamBuilder<List<Passage>>(
initialData: null, //初始的数据
stream: _passageViewModel.stream,
...
这样,我们实现了基本的Stream使用流程。