Guava: 事件总线EventBus

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

 以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中的几个问题?app

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

1、Guava EventBus 观察者模式异步

  首先,咱们声明一个Observer:post

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

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

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

EventBus eventBus = new EventBus();

 而后,把咱们写好的Observer注册进去:线程

eventBus.register(new EventObserver());

 当要通知Observer时,咱们只要这样便可:设计

eventBus.post(message);

 

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

   相比于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/

2、示例

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

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(); 

    } 

}

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

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。。。开始投递"); 

        } 

    } 

} 

 三、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(); 

    } 

}
相关文章
相关标签/搜索