EventBus,也即事件总线。在wiki上有关于Event Monitor的一个说法:java
Event monitoring makes use of a logical bus to transport event occurrences from sources to subscribers, where event sources signal event occurrences to all event subscribers and event subscribers receive event occurrences.
事件监听器经过逻辑总线来将发生的事件从发生源传输到订阅者。事件发生源在事件发生的时候可以发出信号给全部订阅者,订阅者则可以接收到发生的事件。android
我的猜想事件总线这种说法源至于计算机内经常使用的几个总线结构【好比CPU总线,IO总线等】。他们有一个共同的特定就是负责传递某种 object 到指定的地方。好比数据总线负责的是CPU到RAM,地址总线负责的是RAM到RAM传递数据。git
这条词条的分类是在操做系统这个目录下,这也能够理解成是在操做系统较早地使用了这种模式。
在Java内置的包中也有一种EventBus,但它是基于接口的。Google在Guava中实现了一套本身的EventBus,Google实现的总线库更具可读性,由于它使用Annotion标记订阅者和生产者,方法名能够自定义,更具意义。github
在这里先说说Android内置的两种跟EventBus相似的机制。Intent和BroadcastReceiver。
这二者均可以起到跟事件总线相似的效果。注册广播接收器和单纯发一个intent就能够唤起其余组件,提醒其余组件更新,这是很是方便的,同时也是下面提到的两个开源方案所作不到的。
但这种机制也有很差地方,它们内部的实现都须要 IPC,虽然Android的Binder
使得IPC简单了点~~(仍是蛮复杂的吧)~~,但传递效率上会是个问题。若是本身彻底不须要IPC,下面说到的两个项目会更加适合。
在Android中彷佛就只有两个Eventbus的开源项目,Square的otto和GreenRobot的EventBus(如下称GEventBus)。ide
otto是square开源的一个基于Guava的EventBus的项目。跟Guava同样,otto使用Annotion做为事件的标记,@Subscribe
即事件的处理者,@Produce
是基本事件的生产者。举个官方给的例子:函数
<!-- lang: java -->post
@Subscribe public void answerAvailable(AnswerAvailableEvent event) { // TODO: React to the event somehow! } @Produce public AnswerAvailableEvent produceAnswer() { return new AnswerAvailableEvent(this.lastAnswer); } // 订阅者和发布者均须要向同一个总线注册 bus.register(this);
使用起来就是这么简单。订阅者向总线注册,若是此时存在一个生产者,那么这个生产者的方法会被调用以产生一个初始对象来初始化订阅者。另外,在总线接收到对应的事件以后,订阅者的方法就也会被调用。this
bus.post(new AnswerAvailableEvent(100));
post事件并不须要对象向总线注册。post事件后,若是存在事件的订阅者那么订阅者的方法就会被调用。若是不存在订阅者,那么事件会被包裹成DeadEvent
重抛。(待作文章细说)。 默认状况下,otto只支持主线程的事件。好比下面代码所示,bus1和bus2是等价的。若是将策略设置为ANY,那么也能够在非主线程执行。只是不建议,这个库适合的场景也就只是在主线程而已,其余环境下会出现什么情况不作保证。google
Bus bus1 = new Bus(); Bus bus2 = new Bus(ThreadEnforcer.MAIN); // Bus bus3 = new Bus(ThreadEnforcer.ANY);
要想在基类中注册事件要花点心思。(不能经过this来向bus注册事件,由于在子类中的方法调用super到父类方法时,this指的永远是子类)。要想在基类注册事件,基本上只能写一个成员变量,在变量内部注册方法。逻辑会略奇怪。另外,可能须要本身实现一个BusProviderurl
greenrobot的另外一个比较出名的开源项目(另一个是greenDAO)。一样是EventBus,但这个项目不是基于Annotion的。由于Android的Runtime Annotion处理起来效率实在是不高,尤为是在4.0以前。在4.0以后也不见得效率有多大提升。
GEventBus使用的是字符串匹配,默认订阅者会调用带onEvent
或者说是EventBus类里面的DEFAULT_METHOD_NAME
做为前缀的方法。只有仔细跟踪代码以后,你才会发现它的几种线程模型是这么用的:
public void onEvent(SimpleEvent event) {}; public void onEventBackgroundThread(SimpleEvent event) {}; public void onEventMainThread(SimpleEvent event) {}; public void onEventAysnc(SimpleEvent event) {};
其余操做跟otto相似。只是GEventBus不支持生产者方法。(题外话:我是看了otto的demo以后才知道GEventBus的通常用法= =)
onEvent*
方法,不然程序就会崩掉。解决方案,也算有吧,本身实现了一个蛮挫的暂时性解决方案 issus98RuntimeException
,我始终以为GEventBus有问题。注意如下会有不少我的的喜爱致使的吐槽=_=
我的以为最纯正的是otto,即便GreenRobot的EventBus称它的效率比前者高出许多(有benchmark,因此算是事实)。可是一个开源项目,看的并不仅是效率问题吧。
在知乎上看到过一个问题:一个开源软件为什么成功。一个好的开源项目也是同理,其中有个答案提到的几点我很是赞同。
在发现没有Demo以后,我研究过GEventBus的代码。逻辑是搞懂了,但也发觉了GEventBus的代码是如此地不友好,没有关键的注释,名字又表意不清。最最没法容忍的是,它将一堆函数标记为@depreated
,即便如今只能用它们来作。这个Annotion是来这么用的吗?提供了新的替代接口再标记为废弃如何?或者你干脆设置成private好么。
看otto的代码是享受,虽然我只是稍微看了一下,没有深刻去研究。Square彷佛还为otto开发了IntellJ的plugin,能够快速地浏览全部的订阅者和生产者,这点也是GEventBus所不及的吧。
就我的喜爱而言,果真仍是选择otto,用annotion写起来仍是比较顺心的。不像GEventBus,居然要用那么长的名字才能做为事件回调。输入越多,越容易出错,这点不管是在用户体验仍是敲代码的时候都是同理。
我的拙见,欢迎交流>_< 22:09