Event Bus可以说是在客户端界公认的最好的全局通信解决方案了,他的出现简化了应用程序内各组件间、组件与后台线程间的通信。
Event Bus可以说在各大端都有过实现:
Android端的Event Bus
compile 'de.greenrobot:eventbus:3.0.0-beta1'
Ios端的Event Bus
github "cesarferreira/SwiftEventBus" == 3.0.0
Vue更是直接就自带一个EventBus,简直不能再凶残了。那么,既然Event Bus这么不可或缺,Flutter平台肯定也有Event Bus了,对,绝逼是有的。
dependencies:
event_bus: ^1.0.1
class EventBus {
StreamController _streamController;
/// Controller for the event bus stream.
StreamController get streamController => _streamController;
/// new event bus
EventBus({bool sync: false}) {
_streamController = new StreamController.broadcast(sync: sync);
}
///Listener
Stream<T> on<T>() {
if (T == dynamic) {
return streamController.stream;
} else {
return streamController.stream.where((event) => event is T).cast<T>();
}
}
/// Fires a new event on the event bus with the specified [event].
void fire(event) {
streamController.add(event);
}
/// Destroy this [EventBus]. This is generally only in a testing context.
void destroy() {
_streamController.close();
}
很显然,你没有看错,源码就是这么少,相信之前用Rxjava做过RxBus这种风骚操作的你对这么几行代码实现一个Event Bus的你一点都不会觉得惊讶。
而Dart上可以凭借这么几行代码就实现一个Event Bus,同样的道理,背后有着一个分非常有气场的男人在支持,这个男人就是Stream。首先来看一看Event bus的创建。
EventBus({bool sync: false}) {
_streamController = new StreamController.broadcast(sync: sync);
}
创建的过程丢在了构造函数中,使用了broadcast方式,那么什么是broadcast方式呢?要了解这个,还需要知道StreamController的其他方式:
Single subscription streams
broadcast stream
所谓的single方式,是指这种stream流只能被一个人订阅,适用场景是http请求这种。
所谓的broadcast方式,是指这种stream流可以被多个人订阅,but,在你订阅之前的stream已经发送过得事件,你将错过了,只能收到你订阅开始之后发送的事件了。
streamController是dart的内置的一个类,可以理解为给stream制造数据的控制器,公开的方法add(Event)就是干这个的。
当然,这里提到了订阅,那么什么事订阅是怎么做的。
///Listener
Stream<T> on<T>() {
if (T == dynamic) {
return streamController.stream;
} else {
return streamController.stream.where((event) => event is T).cast<T>();
}
}
这里使用泛型T来过滤自己想关心的事件类型,streamController成员stream中holder住了streamContorller制造出来的数据,一定订阅发送,这些数据将一个个的被发送出去,✔️的,每个订阅者都能得到这份数据流。
发送事件很简单,就是使用streamController.add方法往stream中塞事件。
以上就是整个dart实现的event_bus的原理了,用一幅图来解释就是:
fires表示通过StreamController向Streams 中add Event,一旦有了event,subScriptor就嗅到了有货了,于是就取到了fires发送出来的event了。
Stream实际上类比Rxjava的话,就有点类似于Rxjava被订阅之前的那一段。是一个可以被订阅的流,因此,它也有一些比较风骚的操作,比如:
map
Stream<S> map<S>(S Function(T event) convert);
asyncMap
Stream<E> asyncMap<E>(FutureOr<E> Function(T event) convert);
当然,实际上用的最多还是
listen,实际上就是订阅,看其返回值就知道,是StreamSubsciption
StreamSubscription<T> listen(void Function(T event) onData,
因此,如果想取消订阅的话,可以通过StreamSubsciption.cancel来做。这点都是可以我们熟悉的Rxjava类似。
事实上,stream在platform_channel中也有着其举足轻重的地位,做过的同学应该知道EventChannel实际上就是通过stream来实现的。