Flutter實(shí)戰(zhàn) 事件總線

2021-03-08 17:18 更新

在 APP 中,我們經(jīng)常會(huì)需要一個(gè)廣播機(jī)制,用以跨頁面事件通知,比如一個(gè)需要登錄的 APP 中,頁面會(huì)關(guān)注用戶登錄或注銷事件,來進(jìn)行一些狀態(tài)更新。這時(shí)候,一個(gè)事件總線便會(huì)非常有用,事件總線通常實(shí)現(xiàn)了訂閱者模式,訂閱者模式包含發(fā)布者和訂閱者兩種角色,可以通過事件總線來觸發(fā)事件和監(jiān)聽事件,本節(jié)我們實(shí)現(xiàn)一個(gè)簡單的全局事件總線,我們使用單例模式,代碼如下:

  1. //訂閱者回調(diào)簽名
  2. typedef void EventCallback(arg);
  3. class EventBus {
  4. //私有構(gòu)造函數(shù)
  5. EventBus._internal();
  6. //保存單例
  7. static EventBus _singleton = new EventBus._internal();
  8. //工廠構(gòu)造函數(shù)
  9. factory EventBus()=> _singleton;
  10. //保存事件訂閱者隊(duì)列,key:事件名(id),value: 對(duì)應(yīng)事件的訂閱者隊(duì)列
  11. var _emap = new Map<Object, List<EventCallback>>();
  12. //添加訂閱者
  13. void on(eventName, EventCallback f) {
  14. if (eventName == null || f == null) return;
  15. _emap[eventName] ??= new List<EventCallback>();
  16. _emap[eventName].add(f);
  17. }
  18. //移除訂閱者
  19. void off(eventName, [EventCallback f]) {
  20. var list = _emap[eventName];
  21. if (eventName == null || list == null) return;
  22. if (f == null) {
  23. _emap[eventName] = null;
  24. } else {
  25. list.remove(f);
  26. }
  27. }
  28. //觸發(fā)事件,事件觸發(fā)后該事件所有訂閱者會(huì)被調(diào)用
  29. void emit(eventName, [arg]) {
  30. var list = _emap[eventName];
  31. if (list == null) return;
  32. int len = list.length - 1;
  33. //反向遍歷,防止訂閱者在回調(diào)中移除自身帶來的下標(biāo)錯(cuò)位
  34. for (var i = len; i > -1; --i) {
  35. list[i](arg);
  36. }
  37. }
  38. }
  39. //定義一個(gè)top-level(全局)變量,頁面引入該文件后可以直接使用bus
  40. var bus = new EventBus();

使用示例:

  1. //頁面A中
  2. ...
  3. //監(jiān)聽登錄事件
  4. bus.on("login", (arg) {
  5. // do something
  6. });
  7. //登錄頁B中
  8. ...
  9. //登錄成功后觸發(fā)登錄事件,頁面A中訂閱者會(huì)被調(diào)用
  10. 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)共享也有一些專門的包如 redux、以及前面介紹過的 Provider。對(duì)于一些簡單的應(yīng)用,事件總線是足以滿足業(yè)務(wù)需求的,如果你決定使用狀態(tài)管理包的話,一定要想清楚您的 APP 是否真的有必要使用它,防止“化簡為繁”、過度設(shè)計(jì)。

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)