从Stream 到 RxDart
参考:
https://blog.csdn.net/hjjdehao/article/details/104280422
Stream
stream简介
有两种实现异步编程的方式(Future和Stream),使用它们只需要在代码中引入dart:async即可。通过Stream的相关类容及其异步特性来实现简单的响应式编程
Stream的概念可视化与简单化,可以将它想成是管道(pipe)的两端,它只允许从一端插入数据并通过管道从另外一端流出数据。
为了控制Stream,我们通常可以使用StreamController来进行管理;
为了向Stream中插入数据,StreamController提供了类型为StreamSink的属性sink作为入口;StreamController提供stream属性作为数据的出口。
使用Stream中传输的数据时,可以简单地使用listen函数来监听StreamController的stream属性。
在定义完listener(监听者)之后,我们会收到StreamSubscription(订阅)对象,通过这个订阅对象我们就可以接收到Stream发送数据变更的通知。
只要至少有一个活跃的监听者,Stream会创建以下事件来通知订阅对象:
- 数据从Stream中流出;
- Stream接收到错误信息;
- Stream关闭。
响应式编程,主要特征
通过Steam实现响应式编程,主要特征包括:
· 异步性;
· 由Stream和listener组成主要架构;
· 当应用中某处(事件,数值改变...)发生时,Stream会收到这些变化的通知;
· 如果某个监听者监听到Stream的订阅时,它会做出相应的处理,不管在应用的何处;
· 组件之间弱耦合。
Widget只关心自己的业务逻辑!如此一来,看似应用变得无状态,但它会让应用程序具有以下优点:
- 应用中模块职责单一;
- 易于模拟数据以方便测试;
- 方便组件重用;
- 应用易于重构
基于BLoc(Business Logic Component)设计模式模型如下:
1、业务逻辑由一个或多个blocs组成;
2、业务逻辑应该尽量从展示层剥离开来,UI只关心UI层面的问题;
3、使用Stream的高级特性,sink作为输入,stream作为输出;
简单的计数案例:
注意在实际开发当中,一个页面不只有一个bloc,可能有数据处理bloc,事件处理bloc等。
Stream模式的关键思维在于观察者的无状态。我们平时调用方法的时候一定是很清楚我们什么时候调用,并立刻会返回一个预想的结果。
但在这里,我们中间进行处理的时候,完全是处于异步状态的,也就是说无法立刻返回一个值。我们不知道stream什么时候会“吐”出处理结果,所以必须要一个观察者来守着这个出口。当有事件/数据流出时,观察者捕捉到了这个事件并解析处理。
RxDart
RxDart是基于ReactiveX标准API的Dart版本实现,由Dart标准库中Stream扩展而成
常用操作符:
1、迭代地处理数据:map
map方法能够让我们迭代的处理每一个数据并返回一个新的数据
输出:2 3 4 5 6
2、扩展流:expand
expand方法能够让我们把每个item扩展至多个流
输出:1 1.0 2 2.0 3 3.0 4 4.0 5 5.0
3、合并流:merge
merge方法能够让我们合并多个流,请注意输出。
输出:1 4 7 2 5 8 3 6 9
4、检查每一个item:every
every会检查每个item是否符合要求,然后它将会返回一个能够被转化为 Observable 的 AsObservableFuture< bool>。
RxDart提供了三种StreamController的变体来应用到不同的场景:
- PublishSubject:
- BehaviorSubject
- ReplaySubject
PublishSubject
它是最普通的广播StreamController,和StreamController唯一的区别是它返回对象是Observable,而StreamController返回的是Stream。
输出结果:
BehaviorSubject
它是广播StreamController,和PublishSubject的区别是它会额外返回订阅前的最后一次事件。
输出结果:
ReplaySubject
它是广播StreamController,从字面上可以了解到它可以回放已经消失的事件。
输出结果: