EventBus出自greenrobot,和之前大名鼎鼎的GreenDao出自同一家。今天我们将学习分析Event 3.0,EventBus 3.0 最新的特性就是加入了注解,通过注解的方式 告知订阅函数运行在哪个线程中,是一种发布订阅设计模式(观察者设计模式)。。
github地址:https://github.com/greenrobot/EventBus
官方文档:http://greenrobot.org/eventbus/documentation
官网给出的各种角色的协作图
EventBus功能: 通过解耦发布者和订阅者简化Android事件传递,EventBus可以代替Android传统的Intent,Handler,Broadcast或接口函数,在Fragment,Activity,Service线程之间传递数据,执行方法。
EventBus优缺点:
优点:简化组件之间的通信方式,实现解耦让业务代码更加简洁,可以动态设置事件处理线程以及优先级
缺点:目前发现唯一的缺点就是类似之前策略模式一样的诟病,每个事件都必须自定义一个事件类,造成事件类太多,无形中加大了维护成本
compile 'org.greenrobot:eventbus:3.0.0'
订阅
EventBus.getDefault().register(this);//订阅
解除订阅
EventBus.getDefault().unregister(this);//解除订阅
3.)定义一个事件类型
/**
* 传递事件实体类(EventBus发送此类事件给订阅者)
*/
1
2
3
4
5
6
7
8
9
10
11
|
//定义了发送的消息必须是String.
public String Message;
public EventBusMessage(String message) {
Message = message;
|
EventBus.getDefault().post(new EventBusMessage());
/**
* 声明订阅方法:当接收到事件的时候,会调用该方法
* 使用@Subscribe注解
* */
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEvent(EventBusMessage msg) {
Log.d("eventBusThread", "ThreadMode.MAIN " + Thread.currentThread().getName());
}
ThreadMode总共四个:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
加注解提示:在写接收消息的方法是,方法名可以自定义,权限必须是 public ,
参数必须是一个只要接收的参数类型是一致的,那么四个方法都可以接收到发送的信息
ThreadMode.MAIN表示这个方法在主线程中执行
(适合做异步加载,可以将子线程加载到数据直接设置到UI界面里)*/
@Subscribe (threadMode = ThreadMode.MAIN)
public void onEvent(EventBusMessage msg){
//在TextView显示接收的消息,从这个类里拿属性.
tv_title.setText(msg.Message);
Log.d( "eventBusThread" , "ThreadMode.MAIN " +Thread.currentThread().getName());
}
//ThreadMode.POSTING表示该方法和消息发送方在同一个线程.
@Subscribe (threadMode = ThreadMode.POSTING)
public void onEvent(EventBusMessage msg){
Log.d( "eventBusThread" , "ThreadMode.POSTING " +Thread.currentThread().getName());
}
/*ThreadMode.ASYNC也表示在后台执行(也就是子线程执行),可以异步并发处理
(适用于多个线程任务处理,内部有线程池管理,比如请求网络时,用这个方法,他会自动创建线程去请求)
无论发布者是在子线程还是主线程,该方法都会创建一个子线程,在子线程执行.*/
@Subscribe (threadMode = ThreadMode.ASYNC)
public void onEvent(EventBusMessage msg){
Log.d( "eventBusThread" , "ThreadMode.ASYNC " +Thread.currentThread().getName());
}
//ThreadMode.BACKGROUND表示该方法在后台运行(也就是子线程),不能够并发处理
//如果发布者在子线程,那么该方法就在子线程执行
//如果发布者在主线程,那么该方法就会创建一个子线程,在子线程运行.
@Subscribe (threadMode = ThreadMode.BACKGROUND)
public void onEvent(EventBusMessage msg){
Log.d( "eventBusThread" , "ThreadMode.BACKGROUND " +Thread.currentThread().getName());
}
|
发送有序广播可以终止广播的继续往下传递,EventBus也实现了此功能
EventBus.getDefault().cancelEventDelivery(event) ;//优先级高的订阅者可以终止事件往下传递
EventBus黏性事件
概念: 黏性事件就是指在EventBus内部被缓存的那些事件
原理: EventBus为每个类(class)类型保存了最近一次被发送的事件——sticky。后续被发送过来的相同类型的sticky事件会自动替换之前缓存的事件。当一个监听者向EventBus进行注册时,它会去请求缓存事件。这时,缓存的事件就会立即自动发送给这个监听者,有一定的延时性.
EventBus除了普通事件也支持粘性事件,这个有点类似广播分类中的粘性广播。本身粘性广播用的就比较少,为了方便理解成订阅在发布事件之后,但同样可以收到事件。订阅/解除订阅和普通事件一样,但是处理订阅函数有所不同,需要注解中添加sticky = true,是启动黏性事件
1
2
3
4
|
@Subscribe (threadMode = ThreadMode.MAIN,sticky = true )
public void EventBusSticky(EventBusStickyMessage eventBusStickyMessage){
tv_title.setText(eventBusStickyMessage.message);
}
|
发送粘性事件
EventBus.getDefault().postSticky(new EventBusStickyMessage());
如果不需要黏性事件我们可以移除
EventBus.getDefault().removeStickyEvent(new EventBusStickyMessage());
或者调用移除所有粘性事件
EventBus.getDefault().removeAllStickyEvents();