EventBus高级使用姿势

如果你还没用过EventBus,强烈建议你看这篇文章点这里

配置适合业务的EventBus

EventBus中有一个获取默认实例的方法EventBus.getDefault(),默认的EventBus有以下几个特点(包括但不限于)

  • 打印订阅者异常信息
  • 打印没有订阅者的消息
  • 订阅者处理事件出现异常发送异常信息
  • 发送没有订阅者的消息
  • 。。。

基于此,我们需要能自主控制EventBus的一些行为,这时就需要定制适合业务的EventBus
在正式介绍如何定制EventBus之前先介绍一下定制的两种方式
* 使用EventBus.builder()生成一个EventBusBuilder,使用这个EventBusBuilder构造定制的EventBus,然后在所有使用到EventBus的地方使用这个定制的EventBus,这种方式可以定制多种不同行为的EventBus以供使用
* 定制默认的EventBus,使用EventBus.builder().installDefaultEventBus()方法定制默认的EventBus,这种方式定制完成之后使用EventBus.getDefault()方法获得EventBus
以上两种方法各有优劣,各位看官根据业务进行取舍
不管是使用上面两种方法的哪一种,都离不开一个类EventBusBuilder,查看源码可以发现,在EventBusBuilder中右几个默认的属性

    private final static ExecutorService DEFAULT_EXECUTOR_SERVICE = Executors.newCachedThreadPool();

    boolean logSubscriberExceptions = true;
    boolean logNoSubscriberMessages = true;
    boolean sendSubscriberExceptionEvent = true;
    boolean sendNoSubscriberEvent = true;
    boolean throwSubscriberException;//没有赋值的为false
    boolean eventInheritance = true;
    boolean ignoreGeneratedIndex;
    boolean strictMethodVerification;
    ExecutorService executorService = DEFAULT_EXECUTOR_SERVICE;
    List<Class<?>> skipMethodVerificationForClasses;//没有赋值的为null
    List<SubscriberInfoIndex> subscriberInfoIndexes;

如果没有定制默认的EventBus,上面的属性就为默认属性,这些属性会决定EventBus的行为,具体属性控制的行为我们将在以后的源码分析中解释,鉴于此,各位现在知道如何定制EventBus的行为就可以了

Sticky Events(置顶事件)

所谓置顶事件,顾名思义就是后来的消息在先来的消息之上,也就是栈的结构;但是在EventBus中,不是栈的结构,而是后来的消息会把先来的消息覆盖掉,保证消息的最新,不关心以前的消息内容,具体实现会在后面的源码分析中说明。
举个最常见的例子:一个具有定位功能的APP,定位逻辑在Service中,有Service决定什么时候可以发送位置信息,当我们进入一个Activity中时,需要立即获取一个最新的地址信息,但是这个时候Service已经发送完位置信息了,如果我们在Activity中等待位置信息,显然是不友好的,这时就需要使用Sticky Events

首先介绍一下使用方法

EventBus.getDefault().postSticky(new MessageEvent("111","222"));//使用EventBus.postSticky()方法发送置顶事件

编写处理事件方法

@Subscribe(sticky = true, threadMode = ThreadMode.MAIN)//注意此处需要增加sticky = true,表明处理置顶事件
public void handleEvent(MessageEvent event) {
    // UI updates must run on MainThread
    textView.setText(event.message);
}

注册EventBus

EventBus.getDefault().register(this);

有人可能会有疑问,为什么要把注册EventBus放在最后呢,原因是一旦注册了EventBus,置顶事件就会发送到事件处理函数中,具体原理会在后面的源码分析中说明
还有另一种方式获取置顶事件,那就是直接调用方法获取,

MessageEvent stickyEvent = EventBus.getDefault().getStickyEvent(MessageEvent.class);
// Better check that an event was actually posted before
if(stickyEvent != null) {
// "Consume" the sticky event
}

这种方式简单粗暴,不需要注册EventBus,也不需要编写事件处理函数,但是只能显式调用,后面如果还有相同的事件发送出来就不能及时获取到,也就不能及时处理,所以还是需要按需取舍
既然能直接获取到消息,那就应该能移除消息,没错,看下面代码

MessageEvent stickyEvent = EventBus.getDefault().removeStickyEvent(MessageEvent.class);//根据消息的类型移除消息,返回最后的消息内容
boolean b = EventBus.getDefault().removeStickyEvent(event);//根据具体消息进行移除操作,返回移除结果,成功或者失败

上面介绍了两种移除消息的方法,还是按需取舍

观察者的优先级

在EventBus中,观察者也就是Subscription的优先级默认都为0,级别越高,越早收到消息,并且收到消息之后还能阻断后面观察者接收消息,颇有点像有序广播。
注意一下:优先级只是在相同的ThreadMode中才有效,不同的ThreadMode不起作用
首先介绍一下如何使用优先级,上代码:

@Subscribe(priority = 1)//设置优先级为1
public void onEvent(MessageEvent event) {
    //do  something
}

然后如何取消后续的事件传递呢

@Subscribe
public void onEvent(MessageEvent event){
// Process the event
…
EventBus.getDefault().cancelEventDelivery(event) ;//取消事件传递,事件到此为止
}

EventBus 3.X新特性Subscriber Index

简介

注意最开始我们介绍了一些默认属性,在默认属性中有一个属性为ignoreGeneratedIndex,在后面的源码
分析中会介绍到这个属性为true时会使用反射方法获取订阅者的事件处理函数,为false时会使用subscriber Index生成的SubscriberInfo来获取订阅者的事件处理函数,具体内容会在源码分析中介绍
首先,Subscriber Index会在编译期间生成SubscriberInfo,然后在运行时使用SubscriberInfo中保存的事件处理函数处理事件,减少了反射时需要是耗时,会有运行速度上的提升,但是用起来会比较麻烦。。。。

如何使用新特性Subscriber Index

注意事项

只有用注解@Subscriber描述的public方法才能被索引,并且由于Java的特性匿名内部类就算用@Subscriber描述也不能被索引,不过别担心,当EventBus不能使用索引时会自动在运行时使用反射方法获取事件处理函数

使用步骤

  1. 要添加事件处理函数到索引需要借助EventBus的注解处理器,添加EventBus的注解处理器到Module的Gradle文件中:
buildscript {
    dependencies {
        classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
    }
}
apply plugin: 'com.neenbedankt.android-apt'
dependencies {
    compile 'org.greenrobot:eventbus:3.0.0'
    apt 'org.greenrobot:eventbus-annotation-processor:3.0.1'
}
apt {
    arguments {
        eventBusIndex "包名.MyEventBusIndex"//生成索引的名称
    }
}

注意,添加注解处理器的时候还需要添加参数:生成索引的名字
2. 修改完Gradle之后build项目,如果没有错误会自动生成 “eventBusIndex” 文件,这个时候就可以初始化EventBus,上面讲过,自定义EventBus的两种方式,如下代码:

EventBus eventBus = EventBus.builder().addIndex(new MyEventBusIndex()).build();
EventBus.builder().addIndex(new MyEventBusIndex()).installDefaultEventBus();
// Now the default instance uses the given index. Use it like this:
EventBus eventBus = EventBus.getDefault();

不用多说相信你也能明白,顺便说一句,MyEventBusIndex的路径为:项目根目录\build\generated\source\apt\debug\包名\MyEventBusIndex.java
3.如果有多个索引文件还可以使用下面的代码:

EventBus eventBus = EventBus.builder()
    .addIndex(new MyEventBusAppIndex())
    .addIndex(new MyEventBusLibIndex()).build();

如果项目中使用了代码混淆,这一节一定要看!!!

EventBus的事件处理函数在IDE看来是没有被调用的,所以在代码混淆阶段就会被删除!所以必须告诉ProGuard不能删除事件处理函数,上代码:

-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);
}

只要有代码混淆,就需要上述代码!

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值