简介

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. 图像阈值_有cv2.threshold,cv2.adaptiveThreshold 等。

    1.简单阈值 使用的函数:cv2.threshold (src, thresh, maxval, type) 注释: 与名字一样,这种方法非常简单.但像素值高于阈值时,我们给这个像素赋予一个新值(可能 ...

  2. mysql注释的方法

    单行注释:"#", "--", 多行注释:/**/ 参考链接:https://www.cnblogs.com/JiangLe/articles/6897403. ...

  3. 在langchain中使用自定义example selector

    简介 在之前的文章中,我们提到了可以在跟大模型交互的时候,给大模型提供一些具体的例子内容,方便大模型从这些内容中获取想要的答案.这种方便的机制在langchain中叫做FewShotPromptTem ...

  4. 基于python tornado实现的简易图床

    基于python tornado实现的简易图床 项目地址 因为买了阿里/腾讯的云服务器,但是使用云存储还需要收费,又加上家里正好有一台nas,又加上闲的没事,所以搞了一个小脚本 这个项目主要功能是为t ...

  5. Java日志系列:日志门面JCL、SLF4J

    目录 一.日志门面说明 二.JCL 使用 JCL 入门 JCL 原理 三.SLF4J 使用 配合自身简单日志实现(slf4j-simple) 配置logback日志实现 配置Log4J日志实现(需适配 ...

  6. 9、Mybatis之动态SQL

    9.1.环境搭建 9.1.1.创建新module 创建名为mybatis_dynamicSQL的新module,过程参考5.1节 9.1.2.创建Emp实体类 package org.rain.myb ...

  7. cockpit--一款开源的适用于单主机的Linux监控面板

    在搜索Linux监控时,偶然发现一款还不错的监控面板,该面板为red hat开发,适用于各种Linux发行版,部署也非常方便,官方文档Running Cockpit - Cockpit Project ...

  8. 使用 OpenTelemetry 构建 .NET 应用可观测性(2):OpenTelemetry 项目简介

    前世今生 OpenTracing OpenTracing 项目启动于 2016 年,旨在提供一套分布式追踪标准,以便开发人员可以更轻松地实现分布式追踪. OpenTracing 定义了一套 Traci ...

  9. 你准备好了吗,9月19日Java21要来了

    前言 9月份的TIOBE编程语言榜单已公布,Python依然是第一,Java第四. 而这个月还有一个重要的事情,就是9月19日Java21将会全面发布,一段时间没关注的我一口老血喷在屏幕上. 我记得我 ...

  10. 其它——Postman做接口测试

    文章目录 一 介绍 二 下载安装 三 使用 四 批量接口测试(创建collections) 五 导出与导入同事的接口 5.1 导出 5.2 导入 一 介绍 在前后端分离开发时,后端工作人员完成系统接口 ...