EventBus
2019-04-17 本文已影响0人
郑捡书
注册和反注册的位置
EventBus.getDefault().register(this); // 注册
EventBus.getDefault().unregister(this); // 取消注册
在View里面的
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
EventBus.getDefault().register(this);
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
EventBus.getDefault().unregister(this);
}
在Activity
onStart() / onStop()
原理分析
1. EventBus采用单例模式
2. 通过@Subcribe注解声明响应的方法
接收消息
对于EventBus消息的接收,在3.0版本,方法名是任意的,但是必须进行@Subcribe的声明,@Subcribe的定义如下
@Documented
//为运行时注解
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface Subscribe {
//声明该方法运行在哪个线程,默认是发送线程,可见官网解释
// MAIN UI主线程
// POSTING 默认调用方式,在调用post方法的线程执行(),避免了线程切换,性能开销最少
// BACKGROUND 如果调用post方法的线程不是主线程,则直接在该线程执行。如果是主线程,则切换到后台单例线程,多个方法公用同个后台线程,按顺序执行,避免耗时操作
// ASYNC 开辟新独立线程,用来执行耗时操作,例如网络访问。
ThreadMode threadMode() default ThreadMode.POSTING;
/**
* 如果是真,则接收最新的{@link EventBus#postSticky(Object)})消息
*这个可以用来解决界面跳转所带来的消息传递
*/
boolean sticky() default false;
/**
* 优先级,默认是0,数值越大等级越高,等级高的可以取消事件的传递
*/
int priority() default 0;
设置优先级和线程模式
//priority越大,级别越高
@Subscribe(threadMode = ThreadMode.MAIN,priority = 100)
public void onEvent(MainMessage event) {
}
注意中止事件传递,后续事件不再调用(优先级低的订阅者接收不到,类似于有序广播的截断)
@Subscribe
public void onEvent(MessageEvent event){
EventBus.getDefault().cancelEventDelivery(event) ;
}
在取消事件传递的时候有一个注意点,在取消事件传递的方法的线程Mode必须是POSTING的,不然会报event handlers may only abort the incoming event的异常,可以从cancelEventDelivery的源码中看到,在下面代码中的最后一个判断,如果当前事件接收方法不是POSTING,就会抛出这个异常:
public void cancelEventDelivery(Object event) {
PostingThreadState postingState = currentPostingThreadState.get();
if (!postingState.isPosting) {
throw new EventBusException(
"This method may only be called from inside event handling methods on the posting thread");
} else if (event == null) {
throw new EventBusException("Event may not be null");
} else if (postingState.event != event) {
throw new EventBusException("Only the currently handled event may be aborted");
} else if (postingState.subscription.subscriberMethod.threadMode != ThreadMode.POSTING) {
throw new EventBusException(" event handlers may only abort the incoming event");
}
postingState.canceled = true;
}
eventBus粘性事件
EventBus支持粘性事件,粘性事件就是在发送了事件之后,再订阅事件,而不是在发送事件之前订阅,事件接收方法也能收到,通过@Subscribe(sticky = true)去指定,发送事件必须通过postSticky发送。
使用场景 :因为请求接口然后再发送事件再进行控件的更新。有时候该控件所在的页面可能没有初始化好。这时候eventbus所发送的事件就不会起作用。这时候就要用到粘性事件。粘性事件可以先发送事件,待接收方订阅后接受事件。其实就是解决异步所带来的问题。(如同首页请求广告数据,侧边栏还没开启,等开启的时候马上能拿到数据(假设数据已经获取了),但解决方法是可以用Bean缓存起来,然后去指定Bean获取也是一样,感觉粘性事件对于自身的操作习惯来说没什么用)