在Dart庫(kù)中祭隔,有兩種實(shí)現(xiàn)異步編程的方式(Future和Stream)货岭,使用它們只需要在代碼中引入dart:async即可。
Flutter 中疾渴,整個(gè) Stream 主要包含了 StreamController千贯、Sink 、Stream 搞坝、StreamSubscription 四個(gè)對(duì)象搔谴,通過(guò)這四個(gè)對(duì)象來(lái)操控整個(gè)Stream的運(yùn)行。
- StreamController
有一個(gè)事件源叫 Stream桩撮,為了方便控制 Stream 敦第,官方提供了使用 StreamController 作為管理;同時(shí)它對(duì)外提供了 StreamSink 對(duì)象作為事件輸入口店量,可通過(guò) sink 屬性訪問(wèn); 又提供 stream 屬性提供 Stream 對(duì)象的監(jiān)聽和變換芜果,最后得到的 StreamSubscription 可以管理事件的訂閱。
可以說(shuō)融师, StreamController就是如其名字所示一樣用來(lái)管理其他三個(gè)對(duì)象的對(duì)象右钾。
- StreamSink
sink英文的意思為水槽,我們可以將其理解為日常生活中的廚房的洗碗槽诬滩,洗碗槽(sink)中的水(data)會(huì)流進(jìn)管子(stream)中霹粥。一般作為事件的入口,提供如 add 疼鸟, addStream 等后控。
- StreamSubscription
這是一個(gè)事件訂閱后的對(duì)象,空镜,Stream中有兩種訂閱模式浩淘,分別是單點(diǎn)訂閱和廣播捌朴。
表面上用于管理訂閱過(guò)等各類操作,如 cacenl 张抄、pause 砂蔽,同時(shí)在內(nèi)部也是事件的中轉(zhuǎn)關(guān)鍵。
- Stream
事件源本身署惯,一般可用于監(jiān)聽事件或者對(duì)事件進(jìn)行轉(zhuǎn)換左驾,如 listen 、 where 极谊。
什么是Stream诡右?
為了將Stream的概念可視化與簡(jiǎn)單化,可以將它想成是管道(pipe)的兩端轻猖,它只允許從一端插入數(shù)據(jù)并通過(guò)管道從另外一端流出數(shù)據(jù)帆吻。
在Flutter中,
- 我們將這樣的管道稱作Stream咙边;
- 為了控制Stream猜煮,我們通常可以使用StreamController來(lái)進(jìn)行管理败许;
- 為了向Stream中插入數(shù)據(jù)王带,StreamController提供了類型為StreamSink的屬性sink作為入口;
- StreamController提供stream屬性作為數(shù)據(jù)的出口檐束。
class StreamDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('StreamDemo'),
elevation: 0.0,
),
body: StreamTestDemo(),
);
}
}
class StreamTestDemo extends StatefulWidget {
@override
State<StatefulWidget> createState() {
// TODO: implement createState
return StreamTestDemoState();
}
}
class StreamTestDemoState extends State<StreamTestDemo> {
StreamSubscription streamSubscription;
StreamController<String> _streamDemo;
StreamSink _sinkDemo;
var _data = "--";
@override
void initState() {
super.initState();
//使用StreamController 管理Stream
_streamDemo = StreamController<String>();
//為了向Stream中插入數(shù)據(jù)辫秧,StreamController提供了類型為StreamSink的屬性sink作為入口;
_sinkDemo = _streamDemo.sink;
//StreamSubscription 可以管理事件的訂閱 取消 暫停 添加
streamSubscription =
_streamDemo.stream.listen(onData, onError: onError, onDone: onDone);
}
@override
void dispose() {
// TODO: implement dispose
super.dispose();
_streamDemo.close();
}
void onData(String data) {
print('---------${data}');
setState(() {
_data = data;
});
}
void onError(error) {
print('--------error:$error');
}
void onDone() {
print('--------Done');
}
Future<String> fetchData() async {
await Future.delayed(new Duration(seconds: 3));
// throw 'soming err';
return 'hello word';
}
void _addDataToStream() async {
print('------Add data to stream.');
String data = await fetchData();
// _streamDemo.add(data);
_sinkDemo.add(data);
}
void _pauseStream() {
print('------Pause subscription');
streamSubscription.pause();
}
void _resumeStream() {
print('------Resume subscription');
streamSubscription.resume();
}
void _cancelStream() {
print('------Cancel subscription');
streamSubscription.cancel();
}
@override
Widget build(BuildContext context) {
// TODO: implement build
return Container(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(_data),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
FlatButton(
child: Text('Add'),
onPressed: _addDataToStream,
),
FlatButton(
child: Text('Pause'),
onPressed: _pauseStream,
),
FlatButton(
child: Text('Resume'),
onPressed: _resumeStream,
),
FlatButton(
child: Text('Cancel'),
onPressed: _cancelStream,
),
],
),
],
),
),
);
}
}
如下圖 點(diǎn)擊add 后3s后會(huì)顯示hello word 同時(shí)也可以點(diǎn)擊 暫停 恢復(fù) 取消等 查看結(jié)果
另外 Stream 還支持多次訂閱
修改代碼
@override
void initState() {
super.initState();
print('-----Create a stream.');
//支持多次訂閱
_streamDemo = StreamController.broadcast();
_sinkDemo = _streamDemo.sink;
print('-----Start listening on a stream.');
_streamDemoSubscription =
_streamDemo.stream.listen(onData, onError: onError, onDone: onDone);
_streamDemo.stream.listen(onDataTwo, onError: onError, onDone: onDone);
print('-----Initialize completed.');
}
void onDataTwo(String data) {
print('-----onDataTwo: $data');
}
運(yùn)行后便可以查看到兩次的ondata 輸出