flutter-Stream介绍

刚介绍过rxSwift中的Subjects的用法,其实flutter中也有一个类似的概念即Stream.

Stream是Dart中自带的封装,代表着事件流.

根据可订阅数,可以分为:

  • 单订阅流
    单个订阅流在流的整个生命周期内仅允许有一个listener。它在有收听者之前不会生成事件,并且在取消收听时它会停止发送事件,即使你仍然在Sink.add更多事件。即使在第一个订阅被取消后,也不允许在单个订阅流上进行两次侦听.
  • 广播流
    广播流允许任意数量的收听者,且无论是否有收听者,他都能产生事件。所以中途进来的收听者将不会收到之前的消息。

创建单订阅流

1.fromFuture()
  • 接收一个Future对象作为参数
    Stream stream0 = Stream.fromFuture(getData(0));
    stream0.listen((event) {
      print(event);
    }, onError: (msg) {
      print("fromFuture--error=" + msg);
    }, onDone: () {
      print("fromFuture--done");
    });

  Future getData(int i) async {
    return "fromFutures$i";
  }

// I/flutter (31984): fromFutures0
// I/flutter (31984): fromFuture--done
2.fromFutures()
  • 接收Future对象数组作为参数
    List> list = [getData(1), getData(2), getData(3)];
    Stream stream1 = Stream.fromFutures(list);//接收一个Future集合对象作为参数
    stream1.listen((event) {
      print(event);
    }, onError: (msg) {
      print("fromFuture--error=" + msg);
    }, onDone: () {
      print("fromFutures--done");
    });

// I/flutter (31984): fromFutures1
// I/flutter (31984): fromFutures2
// I/flutter (31984): fromFutures3
// I/flutter (31984): fromFutures--done

3.利用StreamController
  • 可以通过sink添加事件
  • 可以添加错误事件,订阅者在onError回调中可以拿到这个错误信息.
    StreamController controller = StreamController(); 
    controller.add("StreamController--add");
    controller.sink.add("StreamController--sink.add");
    controller.addError("error信息");

    StreamSubscription streamSubscription =
        controller.stream.listen((event) {
      print(event);
    }, onError: (msg) {
      print("StreamController--error=" + msg);
    }, onDone: () {
      print("StreamController--done");
    });
    streamSubscription.onDone(() {
      print("done");
    });
    controller.close(); //不关闭会警告
    // streamSubscription.cancel(); //不cancel会警告

// I/flutter ( 1864): StreamController--add
// I/flutter ( 1864): StreamController--sink.add
// I/flutter ( 1864): StreamController--error=error信息

  • 可以添加其他流,同时监听多个流.(但这个流如果是单订阅流,不能被订阅过,否则崩溃)
    controller.addStream(stream2);
Stream stream2 = Stream.fromIterable(
        ["fromIterable1", 'fromIterable2', 'fromIterable3']); //接收一个集合对象作为参数
    // stream2.listen((event) {
    //   print(event);
    // }, onError: (msg) {
    //   print("fromIterable--error=" + msg);
    // }, onDone: () {
    //   print("fromIterable--done");
    // });

    StreamController controller = StreamController(); //StreamController

    controller.add("StreamController--add");

    controller.sink.add("StreamController--sink.add");
    controller.addError("error信息");
    controller.addStream(stream2);

    StreamSubscription streamSubscription =
        controller.stream.listen((event) {
      print(event);
    }, onError: (msg) {
      print("StreamController--error=" + msg);
    }, onDone: () {
      print("StreamController--done");
    });
    streamSubscription.onDone(() {
      print("done");
    });

StreamController使用完成,需要close()
StreamSubscription需要cancle() (在此例中,streamSubscription.cancel()了, 订阅者就收不到消息了,所以实际使用时一般可在State的dispose方法中调用)

4.async*异步生成器
  /// 返回从1-》to的序列流
  Stream countStream(int to) async* {
    //async*异步生成器
    for (int i = 1; i <= to; i++) {
      yield i;
    }
  }

countStream(9).listen((event) {
      print(event);
    });

//I/flutter ( 1864): 1
//I/flutter ( 1864): 2
//I/flutter ( 1864): 3
//I/flutter ( 1864): 4
//I/flutter ( 1864): 5
//I/flutter ( 1864): 6
//I/flutter ( 1864): 7
//I/flutter ( 1864): 8
//I/flutter ( 1864): 9

yield使用语法可参考 https://cloud.tencent.com/developer/article/1633899

  • 这个其中还可以使用一些操作符
    where
countStream(9).where((event) => event % 2 == 0).listen((event) {
      //筛选
      print("where-(event % 2 == 0)--$event");
    });

//I/flutter ( 1864): where-(event % 2 == 0)--2
//I/flutter ( 1864): where-(event % 2 == 0)--4
//I/flutter ( 1864): where-(event % 2 == 0)--6
//I/flutter ( 1864): where-(event % 2 == 0)--8

map

 countStream(9).map((event) => event * 2).listen((event) {
      //变换*2
      print("map变换-event * 2 == 0--$event");
    });
//I/flutter ( 1864): map变换-event * 2 == 0--2
//I/flutter ( 1864): map变换-event * 2 == 0--4
//I/flutter ( 1864): map变换-event * 2 == 0--6
//I/flutter ( 1864): map变换-event * 2 == 0--8
//I/flutter ( 1864): map变换-event * 2 == 0--10
//I/flutter ( 1864): map变换-event * 2 == 0--12
//I/flutter ( 1864): map变换-event * 2 == 0--14
//I/flutter ( 1864): map变换-event * 2 == 0--16
//I/flutter ( 1864): map变换-event * 2 == 0--18

take

 countStream(9).take(4).listen((event) {
      //指定只发送4个事件
      print("take-只发送4个事件 == 0--$event");
    });
//I/flutter ( 1864): take-只发送4个事件 == 0--1
//I/flutter ( 1864): take-只发送4个事件 == 0--2
//I/flutter ( 1864): take-只发送4个事件 == 0--3
//I/flutter ( 1864): take-只发送4个事件 == 0--4

transform

    final transformer =
        StreamTransformer.fromHandlers(handleData: (value, sink) {
      if (value == 9) {
        sink.add("是$value 吗? 你猜对了");
      } else {
        sink.add('是$value 吗? 还没猜中,再试一次吧');
      }
    });

    countStream(9).transform(transformer).listen((event) {
      print(event);
    }, onError: (msg) {
      print("error---" + msg);
    });
//I/flutter ( 1864): 是1 吗? 还没猜中,再试一次吧
//I/flutter ( 1864): 是2 吗? 还没猜中,再试一次吧
//I/flutter ( 1864): 是3 吗? 还没猜中,再试一次吧
//I/flutter ( 1864): 是4 吗? 还没猜中,再试一次吧
//I/flutter ( 1864): 是5 吗? 还没猜中,再试一次吧
//I/flutter ( 1864): 是6 吗? 还没猜中,再试一次吧
//I/flutter ( 1864): 是7 吗? 还没猜中,再试一次吧
//I/flutter ( 1864): 是8 吗? 还没猜中,再试一次吧
//I/flutter ( 1864): 是9 吗? 你猜对了

创建多订阅流

1.单订阅流.asBroadcastStream()
  • StreamController.stream本身是单订阅流 ,只能被订阅一次.
  • StreamController.stream.asBroadcastStream()将单订阅流转成了多订阅流,但是流本身还是StreamController.stream的流,所以下面代码如果先订阅一次StreamController.stream,再订阅一次StreamController.stream.asBroadcastStream(), 代码依然会崩溃.
StreamController controller2 = StreamController();
    Stream broadcastStream = controller2.stream.asBroadcastStream();
//    controller2.stream.listen((event) {
//      print("listen0--");//controller2.stream单订阅流  只能被订阅一次  Bad state: Stream has already been listened to.
//    });
    broadcastStream.listen((event) {
      print("listen1--" + event);
    });
    broadcastStream.listen((event) {
      print("listen2--" + event);
    });
    controller2.add("broadcastStream");
    controller2.close();
//I/flutter ( 1864): listen1--broadcastStream
//I/flutter ( 1864): listen2--broadcastStream
2.StreamController.broadcast()
StreamController controller3 = StreamController.broadcast();
    controller3.stream.listen((event) {
      print("listen1--" + event);
    });
    controller3.stream.listen((event) {
      print("listen2--" + event);
    });
    controller3.add("StreamController.broadcast");
    controller3.close();
//I/flutter ( 1864): StreamController--add
//I/flutter ( 1864): StreamController--sink.add
//I/flutter ( 1864): StreamController--error=StreamController--add--error

StreamBuilder的用法

  • StreamBuilder本身就是一个widget
  • StreamBuilder需要传入一个stream,通过stream内部不同的event值,builder中可以返回不同的widget
  • 可实现局部控件刷新

class StreamPage extends StatefulWidget {
  @override
  _StreamPageState createState() => _StreamPageState();
}

class _StreamPageState extends State {
  StreamController builderController = StreamController();

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    // print(
    //     "单订阅流---------------------------------\n单个订阅流在流的整个生命周期内仅允许有一个listener。它在有收听者之前不会生成事件,并且在取消收听时它会停止发送事件,即使你仍然在Sink.add更多事件。即使在第一个订阅被取消后,也不允许在单个订阅流上进行两次侦听");
    // Stream stream0 = Stream.fromFuture(getData(0)); //接收一个Future对象作为参数
    // stream0.listen((event) {
    //   print(event);
    // }, onError: (msg) {
    //   print("fromFuture--error=" + msg);
    // }, onDone: () {
    //   print("fromFuture--done");
    // });

    // List> list = [getData(1), getData(2), getData(3)];
    // Stream stream1 = Stream.fromFutures(list); //接收一个Future集合对象作为参数
    // stream1.listen((event) {
    //   print(event);
    // }, onError: (msg) {
    //   print("fromFuture--error=" + msg);
    // }, onDone: () {
    //   print("fromFutures--done");
    // });

    // Stream stream2 = Stream.fromIterable(
    //     ["fromIterable1", 'fromIterable2', 'fromIterable3']); //接收一个集合对象作为参数
    // stream2.listen((event) {
    //   print(event);
    // }, onError: (msg) {
    //   print("fromIterable--error=" + msg);
    // }, onDone: () {
    //   print("fromIterable--done");
    // });

    // StreamController controller = StreamController(); //StreamController

    // controller.add("StreamController--add");

    // ///Cannot add event after closing
    // controller.sink.add("StreamController--sink.add");
    // controller.addError("error信息");
    // // controller.addStream(stream2);

    // StreamSubscription streamSubscription =
    //     controller.stream.listen((event) {
    //   print(event);
    // }, onError: (msg) {
    //   print("StreamController--error=" + msg);
    // }, onDone: () {
    //   print("StreamController--done");
    // });
    // streamSubscription.onDone(() {
    //   print("done");
    // });

    // streamSubscription.onDone(() {
    //   print("done");
    // });
    // controller.close(); //不关闭会警告
    // // streamSubscription.cancel(); //不cancel会警告

    // countStream(9).listen((event) {
    //   print(event);
    // });
    // countStream(9).where((event) => event % 2 == 0).listen((event) {
    //   //筛选
    //   print("where-(event % 2 == 0)--$event");
    // });
    // countStream(9).map((event) => event * 2).listen((event) {
    //   //变换*2
    //   print("map变换-event * 2 == 0--$event");
    // });
    // countStream(9).take(4).listen((event) {
    //   //指定只发送4个事件
    //   print("take-只发送4个事件 == 0--$event");
    // });

    // final transformer =
    //     StreamTransformer.fromHandlers(handleData: (value, sink) {
    //   if (value == 9) {
    //     sink.add("是$value 吗? 你猜对了");
    //   } else {
    //     sink.add('是$value 吗? 还没猜中,再试一次吧');
    //   }
    // });

    // countStream(9).transform(transformer).listen((event) {
    //   print(event);
    // }, onError: (msg) {
    //   print("error---" + msg);
    // });

    // print(
    //     "broadcast streams 多订阅流---------\n广播流允许任意数量的收听者,且无论是否有收听者,他都能产生事件。所以中途进来的收听者将不会收到之前的消息。");

    // StreamController controller2 = StreamController();
    // Stream broadcastStream = controller2.stream.asBroadcastStream();
    // // controller2.stream.listen((event) {
    // //   print(
    // //       "listen0--"); //controller2.stream单订阅流  只能被订阅一次  Bad state: Stream has already been listened to.
    // // });
    // broadcastStream.listen((event) {
    //   print("listen1--" + event);
    // });
    // broadcastStream.listen((event) {
    //   print("listen2--" + event);
    // });
    // controller2.add("broadcastStream");
    // controller2.close();

    // StreamController controller3 = StreamController.broadcast();
    // controller3.stream.listen((event) {
    //   print("listen1--" + event);
    // });
    // controller3.stream.listen((event) {
    //   print("listen2--" + event);
    // });
    // controller3.add("StreamController.broadcast");
    // controller3.close();

    Future.delayed(Duration(seconds: 2), () {
      builderController.add("我变化了");
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Stream"),
      ),
      body: StreamBuilder(
          stream: builderController.stream,
          builder: (context, snapshot) {
            return snapshot.hasData
                ? Text(' ${snapshot.data}')
                : Text('waiting for data');
          }),
    );
  }

  // Future getData(int i) async {
  //   return "fromFutures$i";
  // }

  // /// 返回从1-》to的序列流
  // Stream countStream(int to) async* {
  //   //async*异步生成器
  //   for (int i = 1; i <= to; i++) {
  //     yield i;
  //   }
  // }

  @override
  void dispose() {
    builderController.close();
    super.dispose();
  }
}

你可能感兴趣的:(flutter-Stream介绍)