EventBus

作者: 郑捡书 | 来源:发表于2019-04-17 10:01 被阅读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获取也是一样,感觉粘性事件对于自身的操作习惯来说没什么用)

相关文章

网友评论

      本文标题:EventBus

      本文链接:https://www.haomeiwen.com/subject/dgjiuqtx.html