W3Cschool
恭喜您成為首批注冊(cè)用戶(hù)
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
在 APP 中,我們經(jīng)常會(huì)需要一個(gè)廣播機(jī)制,用以跨頁(yè)面事件通知,比如一個(gè)需要登錄的 APP 中,頁(yè)面會(huì)關(guān)注用戶(hù)登錄或注銷(xiāo)事件,來(lái)進(jìn)行一些狀態(tài)更新。這時(shí)候,一個(gè)事件總線便會(huì)非常有用,事件總線通常實(shí)現(xiàn)了訂閱者模式,訂閱者模式包含發(fā)布者和訂閱者兩種角色,可以通過(guò)事件總線來(lái)觸發(fā)事件和監(jiān)聽(tīng)事件,本節(jié)我們實(shí)現(xiàn)一個(gè)簡(jiǎn)單的全局事件總線,我們使用單例模式,代碼如下:
//訂閱者回調(diào)簽名
typedef void EventCallback(arg);
class EventBus {
//私有構(gòu)造函數(shù)
EventBus._internal();
//保存單例
static EventBus _singleton = new EventBus._internal();
//工廠構(gòu)造函數(shù)
factory EventBus()=> _singleton;
//保存事件訂閱者隊(duì)列,key:事件名(id),value: 對(duì)應(yīng)事件的訂閱者隊(duì)列
var _emap = new Map<Object, List<EventCallback>>();
//添加訂閱者
void on(eventName, EventCallback f) {
if (eventName == null || f == null) return;
_emap[eventName] ??= new List<EventCallback>();
_emap[eventName].add(f);
}
//移除訂閱者
void off(eventName, [EventCallback f]) {
var list = _emap[eventName];
if (eventName == null || list == null) return;
if (f == null) {
_emap[eventName] = null;
} else {
list.remove(f);
}
}
//觸發(fā)事件,事件觸發(fā)后該事件所有訂閱者會(huì)被調(diào)用
void emit(eventName, [arg]) {
var list = _emap[eventName];
if (list == null) return;
int len = list.length - 1;
//反向遍歷,防止訂閱者在回調(diào)中移除自身帶來(lái)的下標(biāo)錯(cuò)位
for (var i = len; i > -1; --i) {
list[i](arg);
}
}
}
//定義一個(gè)top-level(全局)變量,頁(yè)面引入該文件后可以直接使用bus
var bus = new EventBus();
使用示例:
//頁(yè)面A中
...
//監(jiān)聽(tīng)登錄事件
bus.on("login", (arg) {
// do something
});
//登錄頁(yè)B中
...
//登錄成功后觸發(fā)登錄事件,頁(yè)面A中訂閱者會(huì)被調(diào)用
bus.emit("login", userInfo);
注意:Dart 中實(shí)現(xiàn)單例模式的標(biāo)準(zhǔn)做法就是使用 static 變量+工廠構(gòu)造函數(shù)的方式,這樣就可以保證
new EventBus()
始終返回都是同一個(gè)實(shí)例,讀者應(yīng)該理解并掌握這種方法。
事件總線通常用于組件之間狀態(tài)共享,但關(guān)于組件之間狀態(tài)共享也有一些專(zhuān)門(mén)的包如 redux、以及前面介紹過(guò)的 Provider。對(duì)于一些簡(jiǎn)單的應(yīng)用,事件總線是足以滿足業(yè)務(wù)需求的,如果你決定使用狀態(tài)管理包的話,一定要想清楚您的 APP 是否真的有必要使用它,防止“化簡(jiǎn)為繁”、過(guò)度設(shè)計(jì)。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號(hào)-3|閩公網(wǎng)安備35020302033924號(hào)
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號(hào)
聯(lián)系方式:
更多建議: