在Android事件總線庫中,EventBus庫是最普遍之一。 看看Android EventBus庫的說明 官網git
咱們要實現一個Flutter版的EventBus!功能以下:github
Demo地址 入口 main_eventbus.dart編程
//發佈者接口 abstract class IPublisher { void post<T>(T event); } //訂閱者:函數對象 typedef ISubscriber<T> = void Function(T event); //集中式通訊, //1.IEventBus繼承IPublisher,分發數據 //2.IEventBus註冊和取消註冊ISubscriber abstract class IEventBus extends IPublisher { void register<T>(ISubscriber<T> subscriber); void unregister<T>(ISubscriber<T> subscriber); } 複製代碼
Type typeOf<T>() => T; class MyEventBus1 implements IEventBus { //咱們用map存放咱們的訂閱者。不一樣訂閱者訂閱的Event類型多是不一樣的 Map<Type, List<Function>> map = new Map(); @override void register<T>(ISubscriber<T> subscriber) { Type type = typeOf<T>(); if (!map.containsKey(type)) { map[type] = new List(); } map[type].add(subscriber); } @override void unregister<T>(ISubscriber<T> subscriber) { Type type = typeOf<T>(); if (map.containsKey(type)) { map[type].remove(subscriber); } } //發佈 @override void post<T>(T event) { Type type = typeOf<T>(); if (map.containsKey(type)) { var subscribers = map[type]; subscribers?.forEach((subscriber) => subscriber?.call(event)); } } } 複製代碼
class MyEventBus2 implements IEventBus { List<Function> subscribers = new List(); @override register<T>(ISubscriber<T> subscriber) { if (!subscribers.contains(subscriber)) { subscribers.add(subscriber); } } @override unregister<T>(ISubscriber<T> subscriber) { if (subscribers.contains(subscriber)) { subscribers.remove(subscriber); } } @override post<T>(T event) { var ints = subscribers.whereType<ISubscriber<T>>(); ints?.forEach((subscriber) => subscriber?.call(event)); } } 複製代碼
class EventX {} class EventY {} main() { testEventBus(new MyEventBus1()); print("--------------------"); testEventBus(new MyEventBus2()); } void testEventBus(IEventBus eventBus) { ISubscriber<EventX> subscriber1 = (event) => print(event.toString()); ISubscriber<EventX> subscriber2 = (event) => print(event.toString()); eventBus.register(subscriber1); eventBus.register(subscriber2); eventBus.unregister(subscriber1); ISubscriber<EventY> subscriber3 = (event) => print(event.toString()); ISubscriber<EventY> subscriber4 = (event) => print(event.toString()); eventBus.register(subscriber3); eventBus.register(subscriber4); eventBus.post(new EventX()); eventBus.post(new EventY()); } 複製代碼
結果輸出爲如下,測試經過redux
Instance of 'EventX' Instance of 'EventY' Instance of 'EventY' -------------------- Instance of 'EventX' Instance of 'EventY' Instance of 'EventY' 複製代碼
點擊每行的按鈕,每行上的兩個數字會增加1 markdown
MyEventBus1 _eventBus = new MyEventBus1(); //首先咱們定義event。第一排用EventA,第二排用EventB class BaseEvent { int count = 0;} class EventA extends BaseEvent {} class EventB extends BaseEvent {} //點擊按鈕 class ButtonWidget<T extends BaseEvent> extends StatelessWidget { final T event; const ButtonWidget({Key key, this.event}) : super(key: key); @override Widget build(BuildContext context) { return RaisedButton( child: Text("increment"), onPressed: _increment, ); } //點擊處理 void _increment() { if (event != null) { event.count++; _eventBus.post(event); } } } //顯示數字 class TextWidget<T> extends StatefulWidget { @override _TextWidgetState<T> createState() { return _TextWidgetState<T>(); } } class _TextWidgetState<T> extends State<TextWidget<T>> { int _count = 0; ISubscriber<T> _subscriber; @override void initState() { super.initState(); //經過setState 刷新UI。 _subscriber = (event) => setState(() => _count = (event as BaseEvent).count); //註冊 _eventBus.register<T>(_subscriber); } @override Widget build(BuildContext context) { return Text( " $_count ", style: TextStyle(fontSize: 18), ); } @override void dispose() { super.dispose(); //取消註冊 _eventBus.unregister<T>(_subscriber); } } //頁面主體 class EventBusDemoWidget1 extends StatefulWidget { EventBusDemoWidget1({Key key}) : super(key: key); @override _EventBusDemoWidget1State createState() => _EventBusDemoWidget1State(); } class _EventBusDemoWidget1State extends State<EventBusDemoWidget1> { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(eventBusDemo1Title), ), body: Container( child: Column( children: <Widget>[ Row( children: <Widget>[ new ButtonWidget(event: new EventA()), new TextWidget<EventA>(), new TextWidget<EventA>() ], ), Divider( color: Colors.grey, ), Row( children: <Widget>[ new ButtonWidget(event: new EventB()), new TextWidget<EventB>(), new TextWidget<EventB>() ], ) ], ), ), ); } } 複製代碼
自定義EventBus大功告成!再來看看別人家的EventBus。app
咱們在pub.dev上找到了一個EventBus庫 ,github地址less
An Event Bus using Dart Streams for decoupling applications異步
實際相對於自定義的EventBus,不一樣點在ButtonWidget和TextWidget中。async
class ButtonWidget<T extends BaseEvent> extends StatelessWidget { final T event; const ButtonWidget({Key key, this.event}) : super(key: key); @override Widget build(BuildContext context) { return RaisedButton( child: Text("increment"), onPressed: _increment, ); } void _increment() { if (event != null) { event.count++; print(event.count); _eventBus.fire(event); // _eventBus.post(event); } } } class TextWidget<T> extends StatefulWidget { @override _TextWidgetState<T> createState() { return _TextWidgetState<T>(); } } class _TextWidgetState<T> extends State<TextWidget<T>> { int _count = 0; // ISubscriber<T> _subscriber; StreamSubscription<T> _subscriber; @override void initState() { super.initState(); // _subscriber = // (event) => setState(() => _count = (event as BaseEvent).count); // _eventBus.register<T>(_subscriber); _subscriber = _eventBus .on<T>() .listen((event) => setState(() => _count = (event as BaseEvent).count)); } @override Widget build(BuildContext context) { print(typeOf<T>()); return Text( " $_count ", style: TextStyle(fontSize: 18), ); } @override void dispose() { super.dispose(); // _eventBus.unregister<T>(_subscriber); _subscriber.cancel(); } } 複製代碼
class EventBus { StreamController _streamController; StreamController get streamController => _streamController; EventBus({bool sync = false}) : _streamController = StreamController.broadcast(sync: sync); EventBus.customController(StreamController controller) : _streamController = controller; Stream<T> on<T>() { if (T == dynamic) { return streamController.stream; } else { return streamController.stream.where((event) => event is T).cast<T>(); } } void fire(event) { streamController.add(event); } void destroy() { _streamController.close(); } } 複製代碼
不由感慨,Dart自帶Stream,處理異步事件。Stream是Dart:async庫的核心API,對異步提供了很是好的支持。 這裏簡單貼圖,體會下Stream。 ide
值得注意的是這句話return streamController.stream.where((event) => event is T).cast<T>(); 複製代碼
返回的Stream包了兩層 CastStream(_WhereStream(_BroadcastStream),經過這樣的處理就能夠監聽泛型事件了。
_WhereStream先處理
class _WhereStream<T> extends _ForwardingStream<T, T> { final _Predicate<T> _test; _WhereStream(Stream<T> source, bool test(T value)) : _test = test, super(source); //_test即爲 (event) => event is T void _handleData(T inputEvent, _EventSink<T> sink) { bool satisfies = _test(inputEvent); if (satisfies) { sink._add(inputEvent); } } } 複製代碼
CastStreamSubscription實際作的類型轉換
class CastStreamSubscription<S, T> implements StreamSubscription<T> { final StreamSubscription<S> _source; /// User's data handler. May be null. void Function(T) _handleData; CastStreamSubscription(this._source) { _source.onData(_onData); } void _onData(S data) { if (_handleData == null) return; T targetData = data as T; _zone.runUnaryGuarded(_handleData, targetData); } 複製代碼
至此,咱們在Provider庫StreamProvider中遇到了Stream,咱們在EventBus庫中遇到了Stream Dart語言自帶優秀的異步編程模型 Stream和Future。 Stream擁有良好的異步模型,滋養了一大波組件庫 Provider/BLoC/flutter_redux/Rxdart/fish-redux。 接下來就有必要對Stream進行分析了。