Stream

前言:Stream和Future均属于dart.async下的核心库,是dart提供的异步操作类。

正文:

一、Stream创建方式

1、Stream.fromFuture通过future对象创建

Stream.fromFuture(init(1));

//初始化函数
Future init(int a) async{
  await Future.delayed(Duration(seconds: 10 - a));
}

2、Stream.fromIterable通过集合创建

Stream.fromIterable([1, 2, 3]);

3、Stream.fromFutures通过Future集合创建

 Stream.fromFutures([init(1), init(2)]);

4、Stream.periodic通过Duration对象创建

//间隔为1秒的无限循环  
var stream = Stream.periodic(Duration(seconds: 1), (data) => data);
stream.listen((event) {
  print("****$event");
});

二、Stream使用

1、stream.take设置事件总数

Stream<int> stream = Stream.periodic(Duration(seconds: 1), (data) => data);
stream = stream.take(4); //一共执行4次事件
stream.listen((event) {
  print("****$event");
});

2、stream.takeWhile当不满足条件时终止

  Stream<int> stream = Stream.periodic(Duration(seconds: 1), (data) => data);
  stream = stream.takeWhile((data) {
    return data < 4;//一共执行4次事件
  });
  stream.listen((event) {
    print("****$event");
  });

3、stream.skip跳过前几条事件

  Stream<int> stream = Stream.periodic(Duration(seconds: 1), (data) => data);
  stream = stream.take(4);
  stream = stream.skip(2);//跳过前两个事件
  stream.listen((event) {
    print("****$event");
  });

4、stream.skipWhile跳过满足条件的事件

  Stream<int> stream = Stream.periodic(Duration(seconds: 1), (data) => data);
  stream = stream.take(4);
  stream = stream.skipWhile((data){
    return data < 2;//跳过前两个事件
  });
  stream.listen((event) {
    print("****$event");
  });

5、stream.toList转成数据集合

Stream<int> stream = Stream.periodic(Duration(seconds: 1), (data) => data);
  stream = stream.take(4);
  List<int> list = await stream.toList();//异步操作需要await
  print("****${list.length}");

6、stream.listen监听事件

  var future1 = Future.delayed(Duration(seconds: 1), (){
    return "Future 1";
  });
  var future2 = Future.delayed(Duration(seconds: 2), (){
    throw "Future 2 error";
  });
  var future3 = Future.delayed(Duration(seconds: 3), (){
    return "Future 3";
  });
  Stream<String> stream = Stream.fromFutures([future1, future2, future3]);
  stream.listen((event) {//每个事件成功回调(必须参数)
    print("****$event");
  }, onError: (e) {//每个事件失败回调
    print("****$e");
  }, onDone: () {//所有事件完成回调
    print("****onDone");
  });

 

注:与future.wait区别在于stream.listen无论是否存在事件失败都会回调onDone而future.wait只有所有事件均成功才会回调,相同点是每个事件均会执行(且并发执行),以下是future.wait的用法

 var future1 = Future.delayed(Duration(seconds: 1), () {
    print("执行事件1");
    return "Future 1";
  });
  var future2 = Future.delayed(Duration(seconds: 2), () {
    print("执行事件2");
    throw "Future 2 error";
  });
  var future3 = Future.delayed(Duration(seconds: 5), () {
    print("执行事件3");
    return "Future 3";
  });
  Future.wait([future1, future2, future3]).then((results) {
    print("results:$results");//所有事件均成功执行后回调
  }).catchError((e) {
    print("catchError:$e");//存在失败事件则会回调
  });

 7、stream.forEach遍历事件

 var stream = Stream.periodic(Duration(seconds: 1), (data) => data);
 stream = stream.take(5);
 stream.forEach((element) {//同listener但只回调onData
   print("****$element");
 });

 8、stream.length事件个数

 var stream = Stream.periodic(Duration(seconds: 1), (data) => data);
 stream = stream.take(5);
 var length = await stream.length;//异步操作需要await
 print("******$length");

9、stream.where执行满足条件的事件

 var stream = Stream.periodic(Duration(seconds: 1), (data) => data);
 stream = stream.where((event) => event < 5);//事件执行5次
 stream.forEach((element) {
   print(element);
 });

10、stream.map数据转换

 var stream = Stream.periodic(Duration(seconds: 1), (data) => data);
 stream = stream.map((event) => event + 3);//对每个数据加3
 stream.forEach((element) {
   print(element);
 });

11、stream.expand事件扩展

 var stream = Stream.periodic(Duration(seconds: 1), (data) => data);
 stream = stream.take(3);
 stream = stream.expand((element) => [element, element]);
 stream.forEach((element) {
   print(element);//输出0 0 1 1 2 2
 });

12、stream.transform数据类型转换

  var stream = Stream.periodic(Duration(seconds: 1), (data) => data);
  stream = stream.take(3);
  var stf = StreamTransformer<int, String>.fromHandlers(handleData: (data, sink) {
    switch (data) {//将int转string
      case 0:
        sink.add("zero");
        break;
      case 1:
        sink.add("one");
        break;
      case 2:
        sink.add("two");
        break;
    }
  });
  stream.transform(stf).forEach((element) {
    print(element);
  });

三、StreamConstroller使用

1、单订阅模式(只允许一个监听即使取消了也不能再次订阅)

  StreamController sc = StreamController();
  StreamSubscription ss = sc.stream.listen((event) {
    print(event);//监听事件
  });
  /*即使取消之前的监听也不能再进行监听
  ss.cancel();
  sc.stream.listen((event) {
    print(event);
  });*/
  sc.sink.add("one");//发送事件
  sc.close();

2、多订阅模式

(1)直接创建方式

  StreamController sc = StreamController.broadcast();
  sc.stream.listen((event) {
    print("监听器1:$event");
  });
  sc.stream.listen((event) {
    print("监听器2:$event");
  });
  sc.sink.add("one");
  sc.close();

(2)单订阅转多订阅方式

  StreamController sc = StreamController();
  var asBroadcastStream = sc.stream.asBroadcastStream();
  asBroadcastStream.listen((event) {
    print("监听器1:$event");
  });
  asBroadcastStream.listen((event) {
    print("监听器2:$event");
  });
  sc.sink.add("one");
  sc.close();

四、StreamBuider使用(实现StatelessWidget中更新UI)

class MainApp extends StatelessWidget {
  int count = 0;
  StreamController sc = StreamController();

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: StreamBuilder(
          stream: sc.stream,//绑定事件流
          builder: (context, snapshot) {//处理事件
            return Text("${snapshot.data}");
          },
        ),
        floatingActionButton: FloatingActionButton(
          child: Icon(Icons.add),
          onPressed: () {
            sc.sink.add(++count);//发送事件
          },
        ),
      ),
    );
  }
}

注:虽然以上可以使StatelessWidget进行更新,但由于StreamController需要在页面销毁时关闭,而StatelessWidget无销毁回调,所以应在StatefulWidget中使用,可在dispose中进行关闭

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值