EventBus优缺点:
优点:简化组件之间的通信方式,实现解耦让业务代码更加简洁,可以动态设置事件处理线程以及优先级
缺点:目前发现唯一的缺点就是类似之前策略模式一样的诟病,每个事件都必须自定义一个事件类,造成事件类太多,无形中加大了维护成本
概述:
EventBus是一款针对Android优化的发布/订阅(publish/subscribe)事件总线。主要功能是替代Intent,Handler,BroadCast在Fragment,Activity,Service,线程之间传递消息。简化了应用程序内各组件间、组件与后台线程间的通信。优点是开销小,代码更优雅。以及将发送者和接收者解耦。比如请求网络,等网络返回时通过Handler或Broadcast通知UI,两个Fragment之间需要通过Listener通信,这些需求都可以通过EventBus实现。
EventBus 三个主要的元素:
Event:事件。可以是任意类型的对象
Subscriber:事件订阅者onEvent,onEventMainThread,onEventBackgroundThread,
onEventAsync ,EventBus 3.0 函数名字不再受到权限
Publisher:事件发布者,可以在任意线程任意位置发送事件
关于ThreadMode:
onEvent: 如果使用onEvent作为订阅函数,那么该事件在哪个线程发布出来的,onEvent就会在这个线程中运行,也就是说发布事件和接收事件线程在同一个线程。使用这个方法时,在onEvent方法中不能执行耗时操作,如果执行耗时操作容易导致事件分发延迟。
onEventMainThread: 如果使用onEventMainThread作为订阅函数,那么不论事件是在哪个线程中发布出来的,onEventMainThread都会在UI线程中执行,接收事件就会在UI线程中运行,这个在Android中是非常有用的,因为在Android中只能在UI线程中跟新UI,所以在onEvnetMainThread方法中是不能执行耗时操作的。
onEventBackground:如果使用onEventBackgrond作为订阅函数,那么如果事件是在UI线程中发布出来的,那么onEventBackground就会在子线程中运行,如果事件本来就是子线程中发布出来的,那么onEventBackground函数直接在该子线程中执行。
onEventAsync:使用这个函数作为订阅函数,那么无论事件在哪个线程发布,都会创建新的子线程在执行onEventAsync。
- NAIN UI主线程
- BACKGROUND 后台线程
- POSTING 和发布者处在同一个线程
- ASYNC 异步线程
基本用法:
- 引入EventBus:
compile 'org.greenrobot:eventbus:3.0.0'复制代码
- 定义事件:
public class MessageEvent { /* Additional fields if needed */ }复制代码
注册事件接收者:
eventBus.register(this);复制代码
发送事件:
eventBus.post(event)复制代码
- 接收消息并处理:
public void onEvent(MessageEvent event) {}复制代码
- 终止事件往下传递
EventBus.getDefault().cancelEventDelivery(event) ;//优先级高的订阅者可以终止事件往下传递复制代码
- 注销事件接收:
eventBus.unregister(this);复制代码
- 混淆
-keepattributes *Annotation*
-keepclassmembers class ** {
@org.greenrobot.eventbus.Subscribe <methods>;
}
-keep enum org.greenrobot.eventbus.ThreadMode { *; }
# Only required if you use AsyncExecutor
-keepclassmembers class * extends org.greenrobot.eventbus.util.ThrowableFailureEvent {
<init>(java.lang.Throwable);
}复制代码
- 最后,proguard 需要做一些额外处理:
#EventBus
-keepclassmembers class ** {
public void onEvent*(**);
void onEvent*(**);
}复制代码
EventBus的粘性事件:
通俗讲是当前页把一个Event发送到一个还没有初始化的Activity/Fragment,即尚未订阅事件。那么如果只是简单的post一个事件,那么是无法收到的,这时候,你需要用到粘性事件,它可以帮你解决这类问题.
- 粘性事件的发布:
EventBus.getDefault().postSticky("RECOGNIZE_SONG");复制代码
- 粘性事件的接收
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
public void receiveSoundRecongnizedmsg(String insType) {
if ("RECOGNIZE_SONG".equals(insType)) {
soundRecognizeCtrl();
}
}复制代码
注意项
同一个onEvent函数不能被注册两次,所以不能在一个类中注册同时还在父类中注册。
消息的接收是根据参数中的类名来决定执行哪一个接收处理方法的。即:订阅者的处理方法是根据订阅事件的类型来确定订阅函数的。
每个事件可以有多个订阅者。
当Post一个事件时,这个事件类的父类的事件也会被Post。
所有事件处理方法必需是public void类型的,并且只有一个参数表示EventType。
EventBus 3.0 与2.x的区别
EventBus 2.x 必须定义以onEvent开头的几个方法,代码中语境比较突兀,且有可能会导致拼写错误,例如数据同步事件
EventBus 3.0 函数名字不再受到权限,而且可以在一个函数中体现出在哪个线程执行,并且可指定接收事件的优先级
EventBus 2.x 注册方式也比较繁琐
EventBus 3.0 注册方式只有一个
EventBus 3.0 性能更优
EventBus 2.x 是采用反射的方式对整个注册的类的所有方法进行扫描来完成注册,当然会有性能上的影响。EventBus 3.0中EventBus提供了EventBusAnnotationProcessor注解处理器来在编译期通过读取@Subscribe()注解并解析、处理其中所包含的信息,然后生成java类来保存所有订阅者关于订阅的信息,这样就比在运行时使用反射来获得这些订阅者的信息速度要快
总结 参考来源