Stream 是什么
异步数据事件的源, 抽象类,用于表示一序列异步数据的源。它是一种产生连续事件的方式,可以生成数据事件或者错误事件,以及流结束时的完成事件。
Stream 分类
流可以分为两类:
-
单订阅流(Single Subscription),这种流最多只能有一个监听器(listener)
-
多订阅流(Broadcast),这种流可以有多个监听器监听(listener)
单订阅流在发送完成事件之前只允许设置一个监听器,并且只有在流上设置监听器后才开始产生事件,取消监听器后将停止发送事件。即使取消了第一个监听器,也不允许在单订阅流上设置其他的监听器。
广播流则允许设置多个监听器,也可以在取消上一个监听器后再次添加新的监听器。
Stream 有同步流和异步流之分。
它们的区别在于同步流会在执行 add,addError 或 close 方法时立即向流的监听器 StreamSubscription 发送事件,而异步流总是在事件队列中的代码执行完成后在发送事件。
Stream 相关对象
StreamController带有控制流方法的流。 可以向它的流发送数据,错误和完成事件,也可以检查数据流是否已暂停,是否有监听器。sync 参数决定这个流是同步流还是异步流。
StreamController _streamController = StreamController(
onCancel: () {},
onListen: () {},
onPause: () {},
onResume: () {},
sync: false,
);
StreamSink流事件的入口。提供 add,addError,addStream 方法向流发送事件
abstract class StreamSink<S> implements EventSink<S>, StreamConsumer<S> {
Future close();
/// ...
Future get done;
}
StreamSubscription流的监听器。提供 cacenl、pause, resume 等方法管理
abstract class StreamSubscription<T> {
/// ...
}
StreamSubscription subscription = StreamController().stream.listen(print);
subscription.onDone(() => print('done'));
StreamBuilder使用流数据渲染 UI 界面的部件
StreamBuilder(
// 数据流
stream: stream,
// 初始数据
initialData: 'loading...',
builder: (context, AsyncSnapshot snapshot) {
// AsyncSnapshot 对象为数据快照,缓存了当前数据和状态
// snapshot.connectionState
// snapshot.data
if (snapshot.hasData) {
Map data = snapshot.data;
return Text(data),
}
return CircularProgressIndicator();
},
)
Stream 创建
- 从现有的生成一个新的流
Stream,使用map,where,takeWhile等方法
// 整数流
Stream<int> intStream = StreamController<int>().stream;
// 偶数流
Stream<int> evenStream = intStream.where((int n) => n.isEven);
// 两倍流
Stream<int> doubleStream = intStream.map((int n) => n * 2);
// 数字大于 10 的流
Stream<int> biggerStream = intStream.takeWhile((int n) => n > 10);
Future对象生成
Future<int> _delay(int seconds) async {
await Future.delayed(Duration(seconds: seconds));
return seconds;
}
List<Future> futures = [];
for (int i = 0; i < 10; i++) {
futures.add(_delay(3));
}
Stream _futuresStream = Stream.fromFutures(futures);
Stream 使用
//创建StreamController
StreamController streamCtrl = StreamController.broadcast();
//用做添加事件的入口
StreamSink get sink => streamCtrl.sink;
//Stream用来监听数据
Stream get stream => streamCtrl.stream;
//Stream的订阅对象
StreamSubscription? subscription1;
StreamSubscription? subscription2;
@override
void initState() {
super.initState();
//监听数据
subscription1 = stream.listen((event) {
print('第一个订阅');
print(event);
});
subscription2 = stream.listen((event) {
print('第二个订阅');
print(event);
});
}
@override
void dispose() {
super.dispose();
//取消订阅
subscription1?.cancel();
subscription2?.cancel();
//关闭流
streamCtrl.close();
}
添加流数据
sink.add('abc');
或
streamCtrl.add('abcd');