如何使用Dart的Stream(一)

Stream 诞生

2018年,谷歌推出了Dart中最重要的一个特性-- Stream。官方对其介绍是:

Widgets + Streams = Reactive Flutter App

简单来说就是,Stream被创建的初衷就是为了实现Flutter的响应式编程。

Stream 简介

Stream(流) 的作用与RxJavaRxJS,或者是Android中 Live Data 非常相似。就如它的名字一样,它代表的是一个异步流,我们可以在代码中的任何地方定义这个,然后在代码中其它任意位置添加数据到这个中, Stream 会监听到数据的改变,并将改变后的数据传递给监听者

在Dart中,代表流的类是 Stream<T> , 但是我们并不会直接操作 Stream 这个类,而是通过SDK中提供的各种工具类来间接使用 Stream ,在这些工具类中提供了各种API来向 Sream 中插入数据,或者通知监听者数据已经处理完毕。

Stream 使用

1. StreamController

其中一个最常用的工具类就是 StreamControllerStreamController 就如同一个管道,在这个管道中封装了一个 Stream ,并向我们提供了两个接口来操作 Stream 。分别是:

  1. sink - 从Stream中的一端插入数据
  2. stream - 从Stream的另一外弹出数据
    在这里插入图片描述
2. 创建 Stream
StreamController<String> controller = new StreamController<String>();
3. 向 Stream 中添加数据

通过StreamController中的sink,向Stream中添加数据:

controller.sink.add("Item1");
controller.sink.add("Item2");
controller.sink.add("Item3");
4. 创建 Stream 监听器

通过StreamController中的stream.listen(),设置监听Stream弹出的数据。listen中传入的是一个函数:

controller.stream.listen((item) => print(item));

在上面的监听方法中,只是简单的将接收的数据给打印出来。

5. Stream监听器的其它方法

Stream.dart 中listen方法的完整声明如下:

/**
 * Adds a subscription to this stream.
 */StreamSubscription<T> listen(void onData(T event),
      {Function onError, void onDone(), bool cancelOnError});

可以看出,除了一个必选参数 onData 函数之外,还有两个可选参数分别是: onErroronDone 。这就意味着,除了简答的接收Stream内弹出的数据data之外,当 Stream 内部处理逻辑发生错误或者处理逻辑已经全部执行完毕,Stream分别会调用 onErroronDone 这两个函数来通知监听者。

我们可以调用sink中的 addErrorclose 方法来触发 onErroronDone 回调。

// 向Stream中添加error
controller.sink.addError('there is a problem!');
controller.sink.close(); // 调用close方法,结束Stream中的逻辑处理
5. Stream 使用完整代码

以下是通过StreamController来操作Stream的完整示例代码:

import 'dart:async';

void main() {
  // 初始化StreamController
  final StreamController controller = StreamController();
  
  // 设置Stream的监听器
  controller.stream.listen(
    (data) => print('data is $data'),
    onError: (err) => print('error happen: $err'),
    onDone: () => print('Mission complete!')
  );

  // 向Stream中添加数据
  controller.sink.add("Item1");
  controller.sink.add("Item2");
  controller.sink.add("Item3");

  // 向Stream中添加error信息
  controller.sink.addError('something wrong here!');
  
  // 关闭StreamController,释放资源
  controller.close();
}

打印结果如下:

data is Item1
data is Item2
data is Item3
error happen: something wrong here!
Mission complete!

Stream 种类

Dart中的Stream有两类:

  1. single-subscription Stream
  2. broadcast Stream

这两者的使用基本相同,唯一的区别就是 single-subscription Streams 只允许被listen一次,而 broadcast stream 可以被listen多次。

single-subscription Stream

之前我们介绍的都属于 single-subscription Stream。如果调用第二次listen,则会报错。比如:

final StreamController controller = StreamController();
// 第一次listen
controller.stream.listen((data) => print('data is $data'));
// 第二次listen会报错
controller.stream.listen((data) => print('data is $data'));

controller.sink.add("Item1");

上述代码会报错:

Unhandled exception:
Bad state: Stream has already been listened to.
#0      _StreamController._subscribe (dart:async/stream_controller.dart:668:7)
#1      _ControllerStream._createSubscription (dart:async/stream_controller.dart:818:19)
#2      _StreamImpl.listen (dart:async/stream_impl.dart:472:9)
#3      main (file:///Users/danny.jiang/Documents/flutter_course/StreamDemo.dart:9:21)
#4      _startIsolate.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:305:19)
#5      _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:172:12)
broadcast Stream

创建 broadcast Stream 的方式如下:

StreamController<int> controller = StreamController<int>.broadcast();  

创建好之后,可以多次listen并多次向Stream中添加数据

StreamSubscription sub1 =  controller.stream.listen((value) => print('sub1 value is $value'));  
controller.sink.add(0);  
controller.sink.add(1);  
  
StreamSubscription sub2 = controller.stream.listen((value) => print('sub2 value is $value'));  
controller.sink.add(2);  
controller.sink.add(3);  

输出结果如下:

sub1 value is 0
sub2 value is 2
sub1 value is 1
sub2 value is 3
sub1 value is 2
sub1 value is 3

可以看出,sub1 可以接收到 Stream 中所有的数据,而 sub2 只能接收到从订阅这个 Stream 之后发送的数据。


关注二维码,发私信申请加入 Flutter 讨论群
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值