简介

EventBus 是一个用于 Android 和 Java 编程的 事件发布/订阅框架。使用 EventBus 进行事件传递,事件的发布订阅就被充分解耦合,这使得编程人员从传统而原始的事件传递方式(诸如Handler、BroadcastReceiver、Interface回调等方式)中解放出来,专注业务逻辑的处理,有助于开发更加优美的程序。

基本概念

  • 事件(Event):也称为消息(Message),一个事件就是一个对象,这个对象里包含着此事件要传递的信息。一类事件属于一个类,不同类型的事件对象所属的类不同。事件有两种类型:

    • 一般事件。一般事件使用时,事件的订阅要在事件的发布之前。
    • 粘滞事件(Sticky Events):如果希望某未订阅事件在发布之后,再订阅该事件时依然能收到该事件,使用粘滞事件。
  • 发布者(Publisher):通常指的是发布某类事件的类。

  • 订阅者(Subscriber):通常指的是订阅某类事件的类。当发布者发布某事件后,EventBus会执行已订阅此事件的订阅者方法,该方法也叫事件处理方法。订阅者须先从 EventBus 注册(register)自身之后才能收到事件。除注册外,还有反注册(unregister)。反注册之后,订阅者不会再收到事件。Android中,如果订阅者是Activity或Fragment,注册和反注册通常根据生命周期来进行。

基本用法

以 Android 中的使用进行介绍。

  1. 添加依赖。

    implementation 'org.greenrobot:eventbus:3.2.0'
  2. 定义事件。事件为无特定要求的 POJO(plain old Java object,简单Java对象)。

    public class MessageEvent {
    
        public final String message;
    
        public MessageEvent(String message) {
    this.message = message;
    }
    }
  3. 指定订阅者。订阅者需要实现事件处理方法(使用@Subscribe注解),以便在事件发布时被调用。自 EventBus 3.0 开始,事件处理方法名称可以任意指定。

    // This method will be called when a MessageEvent is posted (in the UI thread for Toast)
    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onMessageEvent(MessageEvent event) {
    Toast.makeText(getActivity(), event.message, Toast.LENGTH_SHORT).show();
    }

    此外,订阅者还需要从 EventBus 注册 和 反注册 自身。订阅者只有注册自身之后,才可能会收到事件。

    // 根据生命周期注册和反注册
    @Override
    public void onStart() {
    super.onStart();
    EventBus.getDefault().register(this);
    } @Override
    public void onStop() {
    EventBus.getDefault().unregister(this);
    super.onStop();
    }
  4. 发布事件。发布者可以在代码的任何位置发布事件。事件发布后,所有与当前类型事件匹配的已注册订阅者都可以收到该事件。

    EventBus.getDefault().post(new MessageEvent("Hello everyone!"));

高级用法

线程模式(ThreadMode)

EventBus 提供了5个不同的线程模式,用于在与事件发布线程相同或不同的线程中调用订阅者方法。

  1. POSTING

    订阅者将在与发布事件的同一线程中被调用,此为EventBus默认线程模式。事件发布以后立即调用订阅者,且线程不进行切换。该模式要求订阅者方法应快速返回,以避免阻塞发布线程。

    // threadMode 项 可不指定
    @Subscribe(threadMode = ThreadMode.POSTING)
    public void onMessage(MessageEvent event) {
    log(event.message);
    }
  2. MAIN

    订阅者将在Android的主线程(UI线程)中调用。如果发布线程是主线程,此处用法与POSTING模式相同。此处事件处理将会阻塞事件产生,即事件一旦被发布,发布者代码不再往下运行,除非订阅者方法执行完毕。该模式要求订阅者方法应快速返回,以避免阻塞主线程。如果发布线程不是主线程,事件将排入队列。

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onMessage(MessageEvent event) {
    textField.setText(event.message);
    }
  3. MAIN_ORDERED

    订阅者将在Android的主线程(UI线程)中调用。事件始终排入队列,以便在稍后传递给订阅者,因此发布事件的调用将立即返回,订阅者方法执行将在发布事件调用结束之后。该模式使事件处理拥有更严格和更一致的顺序。

    @Subscribe(threadMode = ThreadMode.MAIN_ORDERED)
    public void onMessage(MessageEvent event) {
    textField.setText(event.message);
    }
  4. BACK_GROUND

    订阅者将在后台线程(子线程)中被调用。如果发布线程不是主线程,订阅者方法将直接在发布线程中调用。如果发布线程是主线程, EventBus将使用单个后台线程按顺序传递其所有事件。该模式要求订阅者方法应快速返回,以避免阻塞后台线程。

    @Subscribe(threadMode = ThreadMode.BACKGROUND)
    public void onMessage(MessageEvent event){
    saveToDisk(event.message);
    }
  5. ASYNC

    订阅者方法在单独的线程中被调用,此线程在主线程和发布线程之外。发布线程永远不会阻塞,因为其不等待使用此模式的订阅者方法的返回。如果订阅者方法的执行需要一些时间,使用此模式。

    @Subscribe(threadMode = ThreadMode.ASYNC)
    public void onMessage(MessageEvent event){
    backend.send(event.message);
    }

粘滞事件(Sticky Events)

事件是粘滞事件与否,由发布者发布事件时使用的方法决定:

EventBus.getDefault().postSticky(new MessageEvent("Hello everyone!"));
  • post():发布一般事件
  • postSticky():发布粘滞事件。

某粘滞事件发布后,在订阅者注册期间,当其订阅者方法使用了粘滞事件的标记时,EventBus会将已保留在内存中的此类事件的最后一个事件发送给此订阅者方法。

允许手动获取和删除粘滞事件:

MessageEvent stickyEvent = EventBus.getDefault().getStickyEvent(MessageEvent.class);
// Better check that an event was actually posted before
if(stickyEvent != null) {
// "Consume" the sticky event
EventBus.getDefault().removeStickyEvent(stickyEvent);
// Now do something with it
}

粘滞事件的标记:

@Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
public void onEvent(MessageEvent event) {
textField.setText(event.message);
}

EventBus 简明教程的更多相关文章

  1. 2013 duilib入门简明教程 -- 第一个程序 Hello World(3)

    小伙伴们有点迫不及待了么,来看一看Hello World吧: 新建一个空的win32项目,新建一个main.cpp文件,将以下代码复制进去: #include <windows.h> #i ...

  2. 2013 duilib入门简明教程 -- 部分bug (11)

     一.WindowImplBase的bug     在第8个教程[2013 duilib入门简明教程 -- 完整的自绘标题栏(8)]中,可以发现窗口最大化之后有两个问题,     1.最大化按钮的样式 ...

  3. 2013 duilib入门简明教程 -- 部分bug 2 (14)

        上一个教程中提到了ActiveX的Bug,即如果主窗口直接用变量生成,则关闭窗口时会产生崩溃            如果用new的方式生成,则不会崩溃,所以给出一个临时的快速解决方案,即主窗口 ...

  4. 2013 duilib入门简明教程 -- 自绘控件 (15)

        在[2013 duilib入门简明教程 -- 复杂控件介绍 (13)]中虽然介绍了界面设计器上的所有控件,但是还有一些控件并没有被放到界面设计器上,还有一些常用控件duilib并没有提供(比如 ...

  5. 2013 duilib入门简明教程 -- 事件处理和消息响应 (17)

        界面的显示方面就都讲完啦,下面来介绍下控件的响应.     前面的教程只讲了按钮和Tab的响应,即在Notify函数里处理.其实duilib还提供了另外一种响应的方法,即消息映射DUI_BEG ...

  6. 2013 duilib入门简明教程 -- FAQ (19)

        虽然前面的教程几乎把所有的知识点都罗列了,但是有很多问题经常在群里出现,所以这里再次整理一下.     需要注意的是,在下面的问题中,除了加上XML属性外,主窗口必须继承自WindowImpl ...

  7. Mac安装Windows 10的简明教程

    每次在Mac上安装Windows都是一件非常痛苦的事情,曾经为了装Win8把整台Mac的硬盘数据都弄丢了,最后通过龟速系统恢复模式恢复了MacOSX(50M电信光纤下载了3天才把系统下载完),相信和我 ...

  8. Docker简明教程

    Docker简明教程 [编者的话]使用Docker来写代码更高效并能有效提升自己的技能.Docker能打包你的开发环境,消除包的依赖冲突,并通过集装箱式的应用来减少开发时间和学习时间. Docker作 ...

  9. 2013 duilib入门简明教程 -- 总结 (20)

        duilib的入门系列就到尾声了,再次提醒下,Alberl用的duilib版本是SVN上第个版本,时间是2013.08.15~       这里给出Alberl最后汇总的一个工程,戳我下载,效 ...

  10. plain framework 1 参考手册 入门指引之 简明教程

    简明教程 简单的例子 实现代码 简单的例子 如果你已经下载好整个框架的源码,那么你可以在这里找到应用的例子: plainframework/applications/pf_simple 如果你在win ...

随机推荐

  1. 牛客小白月赛65 D题 题解

    原题链接 题意描述 一共有两堆石子,第一堆有 \(a\) 个,第二堆有 \(b\) 个,牛牛和牛妹轮流取石子,牛牛先手,每次取石子的时候只能从以下 \(2\) 种方案种挑一种来取(对于选择的方案数必须 ...

  2. react中常见hook的使用方式与区别

    1.什么是hook?react hook是react 16.8推出的方法,能够让函数式组件像类式组件一样拥有state.ref.生命周期等属性. 2.为什么要出现hook?函数式组件是全局当中一个普通 ...

  3. 从零开始实现放置游戏(十七)——完结篇(附DEMO地址)

    大家好,时隔2年多,我来填坑啦! 之前用的技术.设计思路都不成熟,所以直接干掉重做了. 由于从头教学实在太啰嗦,精力也有限,咱们还是直接上源码吧. DEMO地址: http://212.129.154 ...

  4. 抢先体验!超强的 Anchor Positioning 锚点定位

    本文,将向大家介绍 CSS 规范中,最新的 Anchor Positioning,翻译为锚点定位. Anchor Position 的出现,极大的丰富了 CSS 的能力,虽然语法稍显复杂,但是有了它, ...

  5. Linux下后台运行Java程序

    1.背景描述 用Java编写了一个程序(可执行的jar),需要在Linux中启动并持续运行 1.1.直接执行程序 直接执行程序后,在程序执行期间,无法在当前会话中再执行其他操作 1.2.直接执行程序后 ...

  6. mysql8关闭binlog并清空Binlog

    编辑my.ini或者my.cnf文件 清空binlog信息 #查看现存的binlog文件列表 show master logs; #重置清空binlog文件 reset master; #重置清空后 ...

  7. KRPANO资源分析工具模板链接下载

    KRPano资源分析工具1.4.0加入了模板链接下载,可以批量下载有规律的链接. 模板链接基本规则 数字递增链接 pic[1-100]:会生成pic1,pic2,-pic100的链接 pic[a-z] ...

  8. flask中cookies的使用

    flask中cookies的使用 在Flask中对cookie的处理 1. 设置cookie: 设置cookie,默认有效期是临时cookie,浏览器关闭就失效 可以通过 max_age 设置有效期, ...

  9. ubuntu实时查看网速

    可以使用ifstat这个命令 安装 apt install ifstat   1 使用,直接打命令就行 ifstat

  10. 单元测验3:亲密关系mooc

    单元测验3:亲密关系 查看帮助 返回   1 单选(2分) 在亲密关系中,有关权力的表述,以下说法不太准确的的是? A. 对关系付出越多,权力越大. B. 大部分人会倾向认为,在恋爱关系中,男女应该拥 ...