事件流是与Flutter相关的一个重要概念,但也是Dart自带的,并不是Flutter独有的。可以将事件流想象成管道的两端,它只允许从一端流入数据并通过管道从另一端流出数据。
事件流可以使用StreamController
来进行管理,StreamController
提供了类型为StreamSink
的sink
属性作为数据的入口,同时也提供了Stream
属性作为数据的出口。事件流传输的数据类型,包括基本类型、事件、对象、集合、Map
等。使用事件流中传输数据时,可以用listen()
方法监听StreamController
的Stream
属性,通过listener
监听,可以收到StreamSubscription
对象,通过StreamSubscription
对象就可以接收事件流发送数据变更的通知。
除了Stream
外,Future
也是异步处理的api。它们的不同之处在于,Future
表示将来
一次异步获取的数据,而Stream
表示多次异步获取的数据。Future
只有一次返回值,而Stream
可以无限次地返回值。
代码示例:
class StreamPage extends StatefulWidget {
final String title;
const StreamPage({
Key? key, required this.title}) : super(key: key);
State<StreamPage> createState() => _StreamPageState();
}
class _StreamPageState extends State<StreamPage> {
final StreamController<int> _streamController = StreamController<int>();
int _counter = 0;
void dispose() {
_streamController.close();
super.dispose();
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text(
'累计的数据',
style: TextStyle(fontSize: 24),
),
StreamBuilder(
stream: _streamController.stream,
initialData: 0,
builder: (BuildContext context, AsyncSnapshot<int> snapshot) {
return Text(
'${
snapshot.data}',
style: const TextStyle(fontSize: 24),
);
}),
OutlinedButton(
onPressed: () => _streamController.sink.add(++_counter),
child: Text(widget.title))
],
),
),
);
}
}
这里是点击按钮来累计数字,并通过_streamController.sink.add(++_counter)
传入数据,然后再界面上通过StreamBuilder
组件监听_streamController.stream
发生的变化并获取值。其中initialData
属性表示一个非空的初始化数据。
除了上面这种使用方式,Stream
还有很多创建方式,比如可以通过Stream.fromFuture(Future future)
创建新的单订阅流,当Future完成时会触发data/error,然后done事件结束。
Future<String> getData() async {
await Future.delayed(const Duration(seconds: 3));
return '当前时间为:${
DateTime.now()}';
}
_streamFromFuture() {
Stream.fromFuture(getData()).listen((event) {
print('Stream.fromFuture:$event');
}).onDone(() {
print('Stream.fromFuture:done');
});
}
总结:Stream
是基于事件流来驱动并设计的代码,可以监听和订阅相关事件,并且对事件进行响应和处理。Flutter提供了很多创建订阅流的方法,比如:Stream.fromIterable(Iterable elements)
通过数据集合获取并创建单订阅流,Stream.fromFutures(Iterable<Future> futures)
通过一系列的Future创建新的单订阅流,等等。