因为当前项目中用到了EventBus,通过阅读源码了解EventBus的实现原理以及优缺点,并对其的一些缺点通过修改源码来进行改进。
EventBus是采用观察者设计模式来实现的事件订阅与发布的消息总线,在Android中用来代替Handler、Message、BroadCast等实现消息的传递和线程的切换等功能。
EventBus的优点
- 代码耦合度低,代码简洁
- 四种线程模型,线程切换方便
- 取代Handler、回调等,代码可读性增强
项目导入EventBus
compile 'org.greenrobot:event:3.0.0'
EventBus的使用
订阅事件:一般在Activity的 onCreate() 或者 onStart() 中订阅事件
EventBus.getDefault().register(this);
取消订阅事件:一般在Activity的 onDestroy() 或者 onPause() 中取消事件的订阅,一般情况下,订阅了事件一定要记得取消订阅事件,否则会造成内存泄漏
EventBus.getDefault().unregister(this);
发布事件
EventBus.getDefault().post(event);
EventBus是通过函数参数类型来判断是否触发对事件的响应,例如同时对LoginEvent和RegisterEvent进行订阅,当发布LoginEvent时,只会调用对LoginEvent订阅了的订阅者,而不会调用对RegisterEvent进行了订阅的订阅者,订阅者的方法必须是public
public void onLogin(LoginEvent event) {
Log.d("Event","login event");
}
public void onRegister(RegisterEvent event) {
Log.d("Event","register event");
}
>EventBus.getDefault().post(LoginEvent);
当同时订阅了LoginEvent和RegisterEvent,上面的代码会触发onLogin
EventBus的线程模型
EventBus包括四种线程模型,分别是 onEvent 、onEventMainThread 、onEventBackgroundThread 和 onEventAsync:
onEvent
对应PostThread模型,事件处理函数将会在事件发送者的线程上执行。这种模式,不需要切换线程,是最快速的,推荐默认采用。
onEventMainThread
对应MainThread模型,事件处理函数将会在主线程上执行。
onEventBackgroundThread
对应BackgroundThread模型,如果发送线程不是主线程,那么事件处理函数将会直接在发送线程调用。如果发送线程是主线程,那么EventBus会启用一个后台线程执行事件处理函数。
onEventAsync
对应Async模型,EventBus会启用一个单独的线程(既不是发送线程,又不是主线程)执行事件处理函数。EventBus会使用线程池,重用线程。
注解Subscribe
通过注解Subscribe,指定线程模型、订阅者的优先级、是否为粘性事件以及我自己扩展的支持参数支持泛型化
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface Subscribe {
ThreadMode threadMode() default ThreadMode.POSTING;
boolean sticky() default false;
int priority() default 0;
/**
* 泛型类型
*/
Class genericsType() default String.class;
}
上面注解Subscribe的源码,包含threadMode、sticky、priority 和 genericsType,其中 genericsType是我通过修改源码添加的,用于解决EventBus不支持泛型参数的问题。
threadMode :指定线程模型,即EventBus回调订阅者时所处的线程,默认为POSTING.
sticky :指定事件是否为粘性事件,即订阅者订阅可收到之前的事件,类似于黏性广播
priority :优先先级,默认为0,值越大代表优先级越高,会越先被调用
genericsType :用于支持参数泛型化,指定特定的参数类型,下一章会详细讲解如何实现
EventBus的缺点
- 由于耦合度太低,代码调试比较困难
- 不支持参数泛型,需要定义各种Event类(修改源码支持泛型化,请关注下一章)
- 使用不当,易造成内存泄漏
- post一个Event时,同参数类型的订阅者都会被调用
EventBus源码地址:https://github.com/greenrobot/EventBus