专栏首页码客Flutter开发-事件总线

Flutter开发-事件总线

事件总线

在APP中,我们经常会需要一个广播机制,用以跨页面事件通知,比如一个需要登录的APP中,页面会关注用户登录或注销事件,来进行一些状态更新。

这时候,一个事件总线便会非常有用,事件总线通常实现了订阅者模式,订阅者模式包含发布者和订阅者两种角色,可以通过事件总线来触发事件和监听事件,本节我们实现一个简单的全局事件总线,我们使用单例模式。

代码如下:

//订阅者回调签名
typedef void EventCallback(arg);

class EventBus {
  //私有构造函数
  EventBus._internal();

  //保存单例
  static EventBus _singleton = new EventBus._internal();

  //工厂构造函数
  factory EventBus()=> _singleton;

  //保存事件订阅者队列,key:事件名(id),value: 对应事件的订阅者队列
  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);
    }
  }

  //触发事件,事件触发后该事件所有订阅者会被调用
  void emit(eventName, [arg]) {
    var list = _emap[eventName];
    if (list == null) return;
    int len = list.length - 1;
    //反向遍历,防止订阅者在回调中移除自身带来的下标错位 
    for (var i = len; i > -1; --i) {
      list[i](arg);
    }
  }
}

//定义一个top-level(全局)变量,页面引入该文件后可以直接使用bus
var bus = new EventBus();

使用示例:

//页面A中
...
//监听登录事件
bus.on("login", (arg) {
  // do something
});

//登录页B中
...
//登录成功后触发登录事件,页面A中订阅者会被调用
bus.emit("login", userInfo);

注意:Dart中实现单例模式的标准做法就是使用static变量+工厂构造函数的方式,这样就可以保证new EventBus()始终返回都是同一个实例,读者应该理解并掌握这种方法。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Docker常用命令

    什么是Docker? Docker就是一个容器,但是这个容器里什么都没有,所以我们根据需求不同就要不同的环境,这些环境就是镜像,我们可以用一个镜像生成多个容器,...

    剑行者
  • Android 音频录制与播放

    剑行者
  • Android 发布个人组件到JCenter

    把BINTRAY_USERNAME 替换成你的bintary上组册的用户名 BINTRAY_KEY 替换成你的 Bintray的API Key 即可

    剑行者
  • TiDB 3.0 GA Release Notes

    2019 年 6 月 28 日,TiDB 发布 3.0 GA 版本,对应的 TiDB Ansible 版本为 3.0.0。

    PingCAP
  • 16.Linux-LCD驱动(详解)

    在上一节LCD层次分析中,得出写个LCD驱动入口函数,需要以下4步: 1) 分配一个fb_info结构体: framebuffer_alloc(); 2) 设置...

    张诺谦
  • 【死磕Java并发】—–J.U.C之Java并发容器:ConcurrentLinkedQueue

    要实现一个线程安全的队列有两种方式:阻塞和非阻塞。阻塞队列无非就是锁的应用,而非阻塞则是CAS算法的应用。下面我们就开始一个非阻塞算法的研究:Coucurren...

    用户1655470
  • java进阶|TreeSet源码分析

    18年冬,利用了周末时间和自己交流了很多,由于交流都是基于代码的形式,没有文字可言,最多是在代码的方法上标注了这个方法是用作什么的,别无其他文字说明,19年秋自...

    后端Coder
  • RPA如何成为解决金融难题的重要选项

    传统金融机构,每天会涉及大量重复性的操作,比如数据调出,客户资料验证等等。这些工作的附加值往往较低,尽管难度不大,但却严重的消耗了公司人力与物力。

    蕉黄
  • 零基础学Flink:监控 on Prometheus & Grafana

    在上一篇文章中,对使用 Prometheus 监控Flink进行了阐述(传送门),这里就不再赘述了。

    麒思妙想
  • 机器学习入门 3-3 NumPy数据基础

    本系列是《玩转机器学习教程》一个整理的视频笔记。本小节主要介绍NumPy模块的一些基础知识。

    触摸壹缕阳光

扫码关注云+社区

领取腾讯云代金券