Guava: 事件总线EventBus

EventBus 直译过来就是事件总线,它使用发布订阅模式支持组件之间的通信,不需要显式地注册回调,比观察者模式更灵活,可用于替换Java中传统的事件监听模式,EventBus的作用就是解耦,它不是通用的发布订阅系统,也不能用于进程间通信。可用于Android的EventBus库主要有这几个:Google出品的Guava,Guava是一个庞大的库,EventBus 只是它附带的一个小功能,因此实际项目中使用并不多。用的最多的是greenrobot/EventBus,这个库的优点是接口简洁,集成方便,但是限定了方法名,不支持注解。另一个库square/otto修改自 Guava ,用的人也不少。

以greenrobot/EventBus 为例,我们看一下 EventBus 模式的典型用法:

// 注册EventBus,接受事件
class Fragment {
    public void onCreate(){
       EventBus.getDefault().register(this);
    }
    public void onDestroy(){
       EventBus.getDefault().unregister(this);
    }
    public void onEvent(SomeEvent1 event){
        // handle event
    }
}

// 处理任务,发送事件
public class Service {
    public void doSomeThing(){
        // do your work
        // send event
        EventBus.getDefault().post(new SomeEvent1());
    }

关于EventBus中的几个问题?

  1. 事件定义:任意的对象即可;
  2. 事件处理器的注册:事件处理的方法,添加注解即可,然后事件处理器的对象注册到总线中,总线维护一个事件和事件处理器的关联关系,在内存中;
  3. 事件的处理过程:同步处理和异步处理,事件提交之后,事件队列维护在本地缓存,同步的方式直接当前线程去执行,异步的处理策略是在初始化事件总线的时候就搞了一个线程池出来,由线程池去异步执行;
  4. EventBus就开放了三个方法,register/post/unregister
  5. 为什么会有unregister?在99.99%的使用场景中,是不会在runtime的时候去register/unregister某个observer的,在spring的环境,也是在init的时候做register/unregister。不过做framework就必须要考虑这0.01%的使用场景。

一、Guava EventBus 观察者模式

首先,我们声明一个Observer:

public class EventObserver {
  @Subscribe public void onMessage(Message message) {
    ...
  }
 }

这个类并没有继承任何接口,只是在用来响应通知的方法上声明了一个@Subscribe。

使用EventBus很简单,先声明一个:

EventBus eventBus = new EventBus();

然后,把我们写好的Observer注册进去:

eventBus.register(new EventObserver());

当要通知Observer时,我们只要这样即可:

eventBus.post(message);

这里,我们并没有告诉EventBus,我们要处理的是一个Message类型,只是在EventObserver的onMessage方法的接口声明上使用了这个类型而已。但是,当我们把消息发送出去的时候,它会根据类型进行匹配,保证我们的消息正确地发送到对应的地方。

相比于JDK原有的实现,这个实现会更简单。EventObserver不再需要存在一个继承体系中,而继承总是一种枷锁,把我们套牢在一个体系之中:

  • 我们不必遵循一个特定的名字,比如Observer的update,而这里的名字onMessage是我们自己起的。
  • 我们不必遵循特定的类型,比如update方法中作为被观察对象Observable和作为参数的Object,而是根据我们自己的需求选择的类型。

这种变换让静态类型的Java语言,有了一些动态类型的特质,也让程序更加灵活。这种灵活性多半要归功于Annotation,它在很大程度上影响了Java的程序设计风格。

除了标准的EventBus,Guava还提供了另外一个AsyncEventBus,从名字就可以看出,这是一个异步的EventBus,也就是说,消息扔给它之后,会立即返回,至于Observer什么时候处理,那就是它的事情了。当处理耗时的处理时很有用,我们要依赖Executors来实现异步事件总线。

AsyncEventBus eventBus = new AsyncEventBus("test", Executors.newCachedThreadPool());

另外:关于EventBus的使用请参见:http://blog.mcxiaoke.com/2015/08/03/how-to-write-an-eventbus-part1/

二、示例

1、一个事件的定义(任何对象都可以是事件)

public class SignEvent {    

    private String companyName; 

    private String signName;    

    private Date signDate; 

    public SignEvent(String name,String signName, Date signDate) { 

        super(); 

        this.companyName = name; 

        this.signName = signName; 

        this.signDate = signDate; 

    }   

    public String getMessage(){ 

        StringBuilder sb = new StringBuilder(); 

        sb.append("物流公司:").append(this.companyName); 

        sb.append("签收人:").append(signName).append(",签收日期:").append(signDate); 

        return sb.toString(); 

    } 

}

2、定义两个事件监听器,添加注解做事件的订阅

public class YTOEventListener { 

    @Subscribe 

    public void consign(SignEvent signEvent){ 

        if(signEvent.getCompanyName().equalsIgnoreCase("YTO")){ 

            System.out.println("YTO。。。开始发货"); 

            System.out.println(signEvent.getMessage()); 

        } 

    } 

    @Subscribe 

    public void delivery(SignEvent signEvent){ 

        if(signEvent.getCompanyName().equalsIgnoreCase("YTO")){ 

            System.out.println("YTO。。。开始投递"); 

        } 

    } 

}

public class SFEventListener {  

    @Subscribe 

    public void consign(SignEvent signEvent){ 

        if(signEvent.getCompanyName().equalsIgnoreCase("SF")){ 

            System.out.println("SF。。。开始发货"); 

            System.out.println(signEvent.getMessage()); 

        } 

    }   

    @Subscribe 

    public void delivery(SignEvent signEvent){ 

        if(signEvent.getCompanyName().equalsIgnoreCase("SF")){ 

            System.out.println("SF。。。开始投递"); 

        } 

    } 

}

3、EventBus的例子,包含时间的注册以及事件的提交

public class EventBusTest { 

    public static void siginalThreadConsumer(){ 

        EventBus bus = new EventBus("iamzhongyong");        

        SFEventListener sf = new SFEventListener(); 

        YTOEventListener yto = new YTOEventListener(); 

        bus.register(sf); 

        bus.register(yto);      

        SignEvent sign1 = new SignEvent("SF","比熊啊",new Date()); 

        bus.post(sign1);        

        SignEvent sign2 = new SignEvent("YTO","你妹的",new Date()); 

        bus.post(sign2);    

    } 

    public static void multiThread(){ 

        EventBus bus = new AsyncEventBus(Executors.newFixedThreadPool(3));      

        SFEventListener sf = new SFEventListener(); 

        YTOEventListener yto = new YTOEventListener(); 

        bus.register(sf); 

        bus.register(yto); 

        SignEvent sign1 = new SignEvent("SF","比熊啊",new Date()); 

        bus.post(sign1);        

        SignEvent sign2 = new SignEvent("YTO","你妹的",new Date()); 

        bus.post(sign2);    

    } 

    public static void main(String[] args) {        

        EventBusTest.siginalThreadConsumer(); 

        EventBusTest.multiThread(); 

    } 

}
时间: 2024-08-03 17:07:02

Guava: 事件总线EventBus的相关文章

自己动手写事件总线(EventBus)

本文由云+社区发表 事件总线核心逻辑的实现. EventBus的作用 Android中存在各种通信场景,如Activity之间的跳转,Activity与Fragment以及其他组件之间的交互,以及在某个耗时操作(如请求网络)之后的callback回调等,互相之之间往往需要持有对方的引用,每个场景的写法也有差异,导致耦合性较高且不便维护.以Activity和Fragment的通信为例,官方做法是实现一个接口,然后持有对方的引用,再强行转成接口类型,导致耦合度偏高.再以Activity的返回为例,一

android事件总线(eventbus)设计与实现

1. 功能介绍 AndroidEventBus是一个Android平台的事件总线库, 它简化了Activity.Fragment.Service等组件或者对象之间的交互,很大程度上降低了它们之间的耦合,使得我们的代码更加简洁,耦合性更低,提升我们的代码质量. AndroidEventBus吸收了greenrobot的EventBus以及square的otto的优点,并在此基础上做出了相应的改进,使得事件总线框架更适合用户的使用习惯,也使得事件的投递更加的精准.灵活. 与EventBus.otto

android事件总线(eventbus)开源库发布

 AndroidEventBus 如果你不知道事件总线是什么,那么没有关系,下面我们先来看这么一个场景: 你是否在开发的过程中遇到过想在Activity-B中回调Activity-A中的某个函数,但Activity又不能手动创建对象来设置一个Listener什么的? 你是否想在某个Service中想更新Activity或者Fragment中的界面? 等等之类的组件之间的交互问题-- 一经思考,你会发现Android中的Activity, Fragment, Service之间的交互是比较麻烦的,

教你自己实现一个事件总线EventBus

EventBus是一个Github上著名的开源事件总线框架,想必很多人都使用过它.它实现了事件订阅者和事件发布者的解耦,让我们更加容易在actvity等组件间传递信息. 我们虽然不喜欢重复造轮子,但是不代表我们不需要了解轮子是怎么造的. 这篇文章通过这个简单的实例,给大家说明EventBus实现的原理,一起来打造一个简单的事件总线框架.如果你明白了这个框架的设计原理,那么EventBus也就相差不大,两者比起来只是后者更加完善和高效. 这也给看源码的朋友带来便利,大家可以先尝试看我这篇文章,再去

事件总线 EventBus

661. .net中事件模型很优雅的实现了观察者模式,同时被大量的使用在各种框架中. [2016-04-30 10:52:42]662. Prism框架中实现了一个典型的EventAggregator,有时候我们又把此类实现叫做EventBus. [2016-04-30 10:53:12]663. EventBus内部通过一个类型为ConcurrentDictionary<Type,List<Action<object>>> 的字典来存储主题和观察者列表 [2016-0

事件总线EventBus使用详解

EventBus源码解析 概述 EventBus是针一款对Android的发布/订阅事件总线.它可以让我们很轻松的实现在Android各个组件之间传递消息,并且代码的可读性更好,耦合度更低. 如何使用 (1)首先需要定义一个消息类,该类可以不继承任何基类也不需要实现任何接口.如: 123 public class MessageEvent { ......} (2)在需要订阅事件的地方注册事件 1 EventBus.getDefault().register(this); (3)产生事件,即发送

ASP.NET Core基于微软微服务eShopOnContainer事件总线EventBus的实现

这个EventBus的实现是基于微软微服务https://github.com/dotnet-architecture/eShopOnContainers项目的,我把它从项目中抽离出来,打包成nuget包方便大家快速集成到项目中 从Nuget.org中安装 PM> Install-Package Toosame.EventBus.RabbitMQ -Version 1.1.2 使用 共3步: 添加事件 添加事件处理器 从控制器发布事件 1.添加事件 创建YourEvent.cs文件 1 publ

Android 开源框架 ( 七 ) 事件总线---EventBus

一.引言          与四大组件之一的BroadCast广播比较,广播主要监听系统级事件,比如网络切换,电池电量等属于进程间的通信,EventBus 是进程内的通信.         了解BroadCast 可以查看该文章:Android 四大组件 (三) BroadcastReceiver 介绍 二.基本使用 引入类库: compile 'com.jakewharton:butterknife:8.5.1' 页面打开时候初始化并注册EventBus //初始化 @Override pro

【java】简单的事件总线EventBus

public class EventBus { private static Map<String, EventListener> eventListeners = new HashMap<>(); public static void addEventListener(EventListener listener) { String listenerName = getListenerName(listener); eventListeners.put(listenerName,