简介
EventBus 是一款订阅——发布模式为核心的开源库 ,EventBus翻译过来是事件总线的意思,一个个事件(event)发送到总线上,然后EventBus根据已注册的订阅者(subscribers)来匹配相应的事件,进而把事件传递给订阅者,这个就是典型的观察者模式
EventBus GitHub地址
对比近似功能
对比广播,这个框架的封装了,没有那么重量级吧个人理解差距不大,handler ,startActivityForResult()等。并且这个也和广播类似有个粘性的概念
使用
1.在Android Studio中添加如下依赖:
compile 'org.greenrobot:eventbus:3.0.0'
2.创建事件实体类,事件实体类,就是传递的事件,一个组件向另一个组件发送的信息可以储存在一个类中,该类就是一个事件,会被EventBus发送给订阅者 ,
如果你想发送字符串可以这样设置你的messageEvent构造 string类型:
EventBus.getDefault().post(new MessageEvent("Hello !....."));
public class MessageEvent {
private String message;
public MessageEvent(String message){
this.message = message;
}
public String getMessage(){
return message;
}
}
3.向EventBus注册,成为订阅者以及解除注册
EventBus.getDefault().register(this);
即可将当前类注册,成为订阅者,即对应观察者模式的“观察者”,一旦有事件发送过来,该观察者就会接收到匹配的事件。通常,在类的初始化时便进行注册,如果是Activity则在onCreate()方法内进行注册。
当订阅者不再需要接受事件的时候,我们需要解除注册,释放内存:
EventBus.getDefault().unregister(this);
4.声明订阅方法
观察者模式,观察者有着一个update()方法,在接收到事件的时候会调用该update()方法,这个方法就是一个订阅方法。在EventBus 3.0中,声明一个订阅方法需要用到@Subscribe注解,因此在订阅者类中添加一个有着@Subscribe注解的方法即可,方法名字可自定义,而且必须是public权限,其方法参数有且只能有一个,另外类型必须为第一步定义好的事件类型(比如上面的MessageEvent),如下所示
@Subscribe
public void onEvent(MessageEvent event) {
/* Do something */
}
5.发送事件
与观察者模式对应的,当有事件发生,需要通知观察者的时候,被观察者会调用notifyObservers()方法来通知所有已经注册的观察者,在EventBus中,对观察者模式底层进行了封装,我们只需要调用以下代码就能把事件发送出去:
EventBus.getDefault().post(EventType eventType);
上面的5个步骤就完成了EventBus 订阅发布了,可能大家比较陌生的就是@Subscribe注解
@Subscribe注解
订阅方法,添加了@Subscribe注解,直接看他的代码。按住点进去
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface Subscribe {
ThreadMode threadMode() default ThreadMode.POSTING;
/**
* If true, delivers the most recent sticky event (posted with
* {@link EventBus#postSticky(Object)}) to this subscriber (if event available).
*/
boolean sticky() default false;
/** Subscriber priority to influence the order of event delivery.
* Within the same delivery thread ({@link ThreadMode}), higher priority subscribers will receive events before
* others with a lower priority. The default priority is 0. Note: the priority does *NOT* affect the order of
* delivery among subscribers with different {@link ThreadMode}s! */
int priority() default 0;
}
内部有三个成员,分别是threadMode、sticky、priority。
threadMode代表订阅方法所运行的线程,
public enum ThreadMode {
POSTING,
MAIN,
BACKGROUND,
ASYNC
}
POSTING:表示订阅方法运行在发送事件的线程
MAIN:表示订阅方法运行在UI线程,由于UI线程不能阻塞,因此当使用MAIN的时候,订阅方法不应该耗时过长
BACKGROUND:表示订阅方法运行在后台线程,如果发送的事件线程不是UI线程,那么就使用该线程;如果发送事件的线程是UI线程,那么新建一个后台线程来调用订阅方法
ASYNC:订阅方法与发送事件始终不在同一个线程,即订阅方法始终会使用新的线程来运行。
一般都是下面的方式,因为我们一般都是要更新UI要回到主线程:
/订阅方法,当接收到事件的时候,会调用该方法
@Subscribe(threadMode = ThreadMode.MAIN)
sticky代表是否是粘性事件,下面再说
priority代表优先级。设置该优先级的目的是,当一个事件有多个订阅者的时候,优先级高的会优先接收到事件。给这个三个成员赋不同的值,能使得订阅方法有着不同的效果。
sticky解释
关于粘性事件,可以参考Android的广播机制,其中有一个粘性广播,粘性广播的意思是:该广播发送后,会保存在内存中,如果后来有注册的Receiver与之匹配,那么该Receiver便会接收到该广播。那么粘性事件同理,在注册之前便把事件发生出去,等到注册之后便会收到最近发送的粘性事件(必须匹配)。注意:只会接收到最近发送的一次粘性事件,之前的会接受不到
如果发送了3个sticky事件,同一个订阅者只会收到最后一个!!!!切记,可以联系观察者模式记忆,观察者是做出三次改变 ,会响应3次,但是这里不会,只会执行最后一次!!!!
结果亲测,版本有限就不贴出了。只会接受到最后发送的粘性事件,在此之前的事件都接收不到!!!
sticky在实际项目中用到的场景
我们公司项目做的基金模块页面就是顶部有多个tab 没个tab 的头部都有一个基金购买风险的提示,用户在这6个tab 每个页面是不同的,但是都存在这个,现在需求就是我点击任意页面的提示 表明我知道这个事情了,然后在其他5个页面都不显示了,这个时候就用的是sticky发送事件