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中的几个问题?
- 事件定义:任意的对象即可;
- 事件处理器的注册:事件处理的方法,添加注解即可,然后事件处理器的对象注册到总线中,总线维护一个事件和事件处理器的关联关系,在内存中;
- 事件的处理过程:同步处理和异步处理,事件提交之后,事件队列维护在本地缓存,同步的方式直接当前线程去执行,异步的处理策略是在初始化事件总线的时候就搞了一个线程池出来,由线程池去异步执行;
- EventBus就开放了三个方法,register/post/unregister
- 为什么会有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();
}
}
Guava: 事件总线EventBus的更多相关文章
- vue中央事件总线eventBus的简单理解和使用
公共事件总线eventBus的实质就是创建一个vue实例,通过一个空的vue实例作为桥梁实现vue组件间的通信.它是实现非父子组件通信的一种解决方案. 用法如下: 第一步:项目中创建一个js文件(我通 ...
- 【bird-java】分布式服务间的事件总线EventBus
什么是EventBusEventBus是对发布-订阅模式的一种实现.其以一种非常优雅的方式实现了组件间的解耦与通信,在Android开发.DDD等领域都有非常广泛的应用. 事件流大致如下: Produ ...
- Android事件总线EventBus详解
顾名思义,AndroidEventBus是一个Android平台的事件总线框架,它简化了Activity.Fragment.Service等组件之间的交互,很大程度上降低了它们之间的耦合,使我们的代码 ...
- 自己动手写事件总线(EventBus)
本文由云+社区发表 事件总线核心逻辑的实现. EventBus的作用 Android中存在各种通信场景,如Activity之间的跳转,Activity与Fragment以及其他组件之间的交互,以及在某 ...
- C# 事件总线 EventBus
1. 引言 事件总线这个概念对你来说可能很陌生,但提到观察者(发布-订阅)模式,你也许就很熟悉.事件总线是对发布-订阅模式的一种实现.它是一种集中式事件处理机制,允许不同的组件之间进行彼此通信而又不需 ...
- 事件总线EventBus
什么是事件总线管理? 将事件放到队列里,用于管理和分发: 保证应用的各个部分之间高效的通信及数据,事件分发: 模块间解耦: 什么是EventBus? EventBus是发布/订阅的事件总线.Event ...
- ASP.NET Core基于微软微服务eShopOnContainer事件总线EventBus的实现
这个EventBus的实现是基于微软微服务https://github.com/dotnet-architecture/eShopOnContainers项目的,我把它从项目中抽离出来,打包成nuge ...
- 事件总线 EventBus
661. .net中事件模型很优雅的实现了观察者模式,同时被大量的使用在各种框架中. [2016-04-30 10:52:42]662. Prism框架中实现了一个典型的EventAggregator ...
- 基于ASP.NET Core 5.0使用RabbitMQ消息队列实现事件总线(EventBus)
文章阅读请前先参考看一下 https://www.cnblogs.com/hudean/p/13858285.html 安装RabbitMQ消息队列软件与了解C#中如何使用RabbitMQ 和 htt ...
随机推荐
- Spring入门(10)-Spring JDBC
Spring入门(10)-Spring JDBC 0. 目录 JdbcTemplate介绍 JdbcTemplate常见方法 代码示例 参考资料 1. JdbcTemplate介绍 JdbcTempl ...
- 递归函数recursion
1(调用自身)递归函数是‘自己调用自己‘的函数,不管这样的调用是直接的还是间接的. 2(递归出口)因为函数不可以一直调用自己,无法停止工作,所以递归函数一定具备结束条件. http://www.cnb ...
- 用6个字符写出任意的Javascript代码
博客搬到了fresky.github.io - Dawei XU,请各位看官挪步.最新的一篇是:用6个字符写出任意的Javascript代码.
- android ipc通信机制之之三,进程通讯方式。
IPC通讯方式的优缺点: IPC通讯方式的对比 名称 优点 缺点 适用场景 Bundle 简单易用 只能传输Bundle支持的数据类型 四大组件的进程通信 文件共享 简单易用 不适合高并发场景,并无法 ...
- Actions 动作集
--> 移动鼠标到指定位置(先触发onMouseOver动作) Actions action = new Actions(driver); WebElement th ...
- cc2530 makefile简略分析 <contiki学习之三>
前面将contiki的makefile框架都理了下,这篇就以cc2530为收篇吧,也即makefile分析就该到此为止了. contiki/examples/cc2530dk 打开Makefile如下 ...
- flash的dragonbone插件导入cocos2d的注意事项
一:Flash版本号应该为CS 6.0,低版本号不提供支持 二:新建flash项目的时候应该选择ActionScript3.0 三:动画中仅仅有两种元素,一个是"元件",还有一个是 ...
- 【WinForm】C# 发送Email
发送Email 的条件 1.SmtpClient SMTP 协议 即 Host 处理事务的主机或IP地址 //smtp.163.com UseDefaultCredentia ...
- bzoj 4300: 绝世好题 dp
4300: 绝世好题 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/problem.php ...
- Codeforces Gym 100610 Problem K. Kitchen Robot 状压DP
Problem K. Kitchen Robot Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/10061 ...