Future和Stream类是Dart异步编程的核心。
Future 表示一个不会立即完成的计算过程。与普通函数直接返回结果不同的是异步函数返回一个将会包含结果的 Future。该 Future 会在结果准备好时通知调用者。
Stream 是一系列异步事件的序列。其类似于一个异步的 Iterable,不同的是,当你向 Iterable 获取下一个事件时它会立即给你,但是 Stream 则不会立即给你而是在它准备好时告诉你。
Future和Stream的本质区别是:Future中的任务会加入下一轮事件循环,而Stream中的任务则是加入微任务队列。
Future 用于表示单个运算的结果,而 Stream 则表示多个结果的序列。
Stream中的执行异步的模式就是scheduleMicrotask。因为microtask的优先级又高于event。
所以,如果 microtask 太多就可能会对触摸、绘制等外部事件造成阻塞卡顿。
一个Stream可以通过Stream.fromFuture方法将一个Future转换为Stream, 也可以通过Stream.fromFutures将多个Future添加到Stream中。
Stream分为Single Subscription和Broadcast两种类型, 前者只允许订阅(listen)一次,后者允许多次订阅。
// 1. Single-Subscription
var data = [1, 2, '3.toString()', true, true, false, true, 6];
Stream stream = Stream.fromIterable(data).distinct();
stream.listen((event) => print('Liste1 -> Stream.fromIterable -> $event')).onDone(() => print('onDone1 -> Stream.fromIterable -> done 结束'));
stream //报错.listen((event2) => print('Liste2 -> Stream.fromIterable -> $event2')).onDone(() => print('onDone2 -> Stream.fromIterable -> done 结束'));
// 2. Broadcast 所有数据被打印两次
var data = [1, 2, '3.toString()', true, true, false, true, 6];
Stream stream = Stream.fromIterable(data).distinct();
stream = stream.asBroadcastStream();
stream.listen((event) => print('Liste1 -> Stream.fromIterable -> $event')).onDone(() => print('onDone1 -> Stream.fromIterable -> done 结束'));
stream .listen((event2) => print('Liste2 -> Stream.fromIterable -> $event2')).onDone(() => print('onDone2 -> Stream.fromIterable -> done 结束'));
通过StreamController向Stream中添加数据:
//1. 通过StreamController创建stream并添加数据(1)
StreamController<String> _streamControler = StreamController<String>();
_streamControler.stream.listen(onData:onData, onError: onError, onDone: onDone);
_streamControler.add(await getData());//2. 通过StreamController的Sink添加数据(2)
StreamController<String> _streamControl = StreamController<String>();
Sink _sink=_streamControler.sink;
_sink.add(await getData());
通过StreamBuilder可以用来实现界面的异步构建,其作用类似于FutureBuilder。但StreamBuilder能力更强,可以等待多个异步事件完成,然后再执行Widget的构建。
StreamBuilder<List<String>>(stream: dataStream,initialData: ["none"],///这里的 snapshot 是数据快照的意思builder: (BuildContext context, AsyncSnapshot<List<String>> snapshot) {///获取到数据,为所欲为的更新 UIvar data = snapshot.data;return Container();});