概述
方法 | 特点 |
---|---|
EventBus | 开销小,代码更优雅,将发送者和接收者解耦 |
Otto | 降低程序之间的耦合性 |
一、EventBus简介
EventBus是一个发布-订阅的事件总线。Event Bus模式也被称之为Message Bus或者发布者-订阅者模式,它简化了应用程序内各组件间、组件与后台线程间的通信,可以让两个组件相互通信,但是它们之间并不相互知晓(有些类似于广播机制)。其优点是开销小,代码更优雅,以及将发送者和接收者解耦。其主要功能是用来替代传统的Intent、Handler、Broadcast在Fragment、Activity、Service以及线程之间传递消息。
目前有多个库都开发了这样的功能。比如说:Google guava 开源库,位于com.google.common.eventbus包下面。但是guava项目比较大,比较常用在j2ee项目内。我们在android开发中实际用的是greenrobot 开发的EventBus。它有以下的优点:1、方法库较小,便于集成。guava jar包2.2M,greenrobot 54k;2、使用简单;
EventBus是彻底解耦的观察者模式。我们常常用在对象一对多的情况,使一个对象发生改变的时候,所有依赖的对象能够得到通知并更新。比如我们在实际的开发中,当用户登录了,我们多个页面需要根据登录后的信息更改页面UI。这时,登录界面就是发布者,而其他的页面就是订阅者。它们都在订阅用户信息变化的消息。再比如我们的Fragment间的通信。
优点:1、开发简便;2、代码耦合度降低;3、插件大小合适,仅54k;
缺点:由于是松耦合设计,导致代码维护差,发送出来的事件不知道有多少个接收者。
二、EventBus的概述
1、分发流程
(1)发送者(Publisher)首先把它的事件(Event)传递到事件总线(EventBus)里面进行管理,等待分发。
(2)事件总线(EventBus)按照相应的逻辑,遍历所有已经注册事件(Event)的订阅者(Subscribe),找到onEvent()方法,把事件(Event)发布给订阅者(Subscriber)。
(3)订阅者(Subscriber)接收到数据(通过对应方法进行接收),进行相应的处理。
2、三要素
元素名称 | 说明 |
---|---|
Event | 事件 |
Subscriber | 事件订阅者,接收特定的Event事件 |
Publisher | 事件发布者,用于通知Subscriber有事件发生 |
Event:事件。它可以是任意类型。
Subscriber:事件订阅者。在EventBus3.0之前我们必须定义onEvent、onEventMainThread、onEventBackgroundThread和onEventAsync四种方法,它们代表四种线程模型。而在3.0之后事件处理的方法名可以随意取,不过需要加上注解@subscribe(),并且指定线程模型,默认是POSTING。
Publisher:事件的发布者。可以在任意线程任意位置发布事件,直接调用EventBus的post(Object)方法。一般情况下,使用EventBus.getDefault()就可以得到一个EventBus对象,然后再调用post(Object)方法即可。
注意:订阅者参数类型必须和发布的参数一致。
3、四种线程模型
EventBus3.0有四种线程模型,分别是:
POSTING (默认):表示发布事件和接收事件在同一个线程。
MAIN:表示事件处理会在主线程(UI)线程执行,因此在这里不能进行耗时操作。
BACKGROUND:表示事件处理函数的线程在后台线程,因此不能进行UI操作。如果发布事件的线程是主线程(UI线程),那么事件处理函数将会开启一个后台线程,如果果发布事件的线程是在后台线程,那么事件处理函数就使用该线程。
ASYNC:表示无论事件发布的线程是哪一个,事件处理函数始终会新建一个子线程运行,同样不能进行UI操作。
三、EventBus的基本用法
EventBus的基本用法包括订阅、注册、发布、取消注册。
1、注册:
EventBus.getDefault().register(this);
EventBus.getDefault().register(new MyClass());
//注册:三个参数分别是,消息订阅者(接收者),接收方法名,事件类
EventBus.getDefault().register(this,“setTextA”,SetTextAEvent.class);
2、取消注册:
EventBus.getDefault().unregister(this);
EventBus.getDefault().unregister(new MyClass());
3、订阅处理数据:
public void onEventMainThread{}
public void onEvent(AnyEventType event) {}
onEventPostThread、onEventBackgroundThread、onEventAsync
4、发布:
EventBus.getDefault().postSticky(new SecondActivityEvent(“Message From SecondActivity”));
EventBus.getDefault().post(new ChangeImgEvent(1));
四、版本迭代
1、EventBus 2.4.1
- 导入EventBus,将EventBus 2.4.1的jar包。下载地址 http://search.maven.org/
- 在需要接收事件的组件注册为订阅者(接收事件的页面)。EventBus.getDefault().register(this);
- 自定义通知事件的类,我们惯例起名为XXXEvent。
- 在订阅者类中接收事件。
- 在需要发送事件的地方EventBus.getDefault().post;
- 使用完成注销 EventBus.getDefault.unregister(this);
EventBus 在3.0.0版本以下的接收事件方法都是才有约定好的方法进行接收。EventBus提供了以下几个方法进行接收事件:
onEvent() 执行在发送事件的线程。 onEventMainThread 代表这个方法会在UI线程执行
onEventPostThread 代表这个方法会在当前发布事件的线程执行
onEventBackgroundThread 事件处理是在后台线程,但事件处理时间还是不应该太长,因为如果发送事件的线程是后台线程,会直接执行事件,
如果当前线程是UI线程,事件会被加到一个队列中,由一个线程依次处理这些事件,如果某个事件处理时间太长,会阻塞后面的事件的派发或处
理。
onEventAsync 每个事件会开启一个线程(有线程池),但最好限制线程的数目
2、EventBus 3.0.0
- 导入EventBus 3.0.0,可以使用Gradle:compile ‘org.greenrobot:eventbus:3.0.0’,也可以去下载jar包
- 在需要接收事件的组件注册为订阅者(接收事件的页面)。EventBus.getDefault().register(this);
- 自定义通知事件的类,我们惯例起名为XXXEvent。
- 在订阅者类中接收事件。
- 在需要发送事件的地方EventBus.getDefault().post;
- 使用完成注销 EventBus.getDefault.unregister(this);
在EventBus 3.0.0 以后EventBus 取消了约定好的方法定义,并提供了注解的方式进行监听。
@Subscribe(threadMode = ThreadMode.MAIN)
public void getEventBus(MyEvent event){
}
threadMode 就是旧版本接收信息运行的方法。
- MainThread 主线程
- BackgroundThread 后台线程
- Async 后台线程
- PostThread 发送线程(默认)
五、EventBusDemo
在Android Studio中不需要下载jar包,直接添加依赖即可:
compile 'org.greenrobot:eventbus:3.0.0'
项目简介:使用EventBus进行事件的注册、订阅和发布。
项目地址:https://github.com/ambition-hb/EventBusDemo
项目图示:
首先点击MainActivity中的“注册事件”按钮来注册事件,然后点击“调转到SecondActivity”按钮,这时跳转到SecondActivity,接下来点击“发送事件”按钮,这个时候SecondActivity被finish掉,因此界面显示的是MainActivity以及TextView“您已收到SecondActivity发送的事件!”,至此,MainActivity成功地收到了SecondActivity发送的事件。
部分代码如下:
//1、MessageEvent.java
public class MessageEvent {
//定义消息事件类
private String message;
public MessageEvent(String message){
this.message = message;
}
public String getMessage(){
return message;
}
public void setMessage(String message){
this.message = message;
}
}
//2、MainActivity.java
public class MainActivity extends AppCompatActivity {
private Button bt_message;//跳转到SecondActivity
private Button bt_subscription;//注册事件
private TextView tv_message;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(</