一、简介
EventBus GitHub地址:https://github.com/greenrobot/EventBus
EventBus是Android的一个开源项目,它最重要的功能就是可以简化各个组件之间的消息传递。EventBus是Android和Java的发布/订阅事件总线。EventBus主要优点:
- 简化了组件之间的通信,使Activity与Fragment以及线程之间的通信简单化,避免了复杂且容易出错的依赖性和生命周期问题;
- 将事件发送者和注册者分开,低耦合,让你的代码更简单,逻辑更清晰;
- EventBus内存开销小,并且效率高等;
- EventBus还可以设置消息接受的优先级,以及运行在哪个线程。
下面看下GitHub上提供的示意图,逻辑很清晰,通过post方法,将消息推送给所有注册该对应消息的对象,并调用对应的方法。
在AndroidStudio中添加依赖库:compile 'org.greenrobot:eventbus:3.1.1' 或者可以下载对应的jar包集成到自己的项目中Jar包下载地址
二、EventBus使用步骤
主要分三个步骤:
- 定义消息体。
- 准备订阅者,用@Subscribe 注解定义你的订阅方法,可以指定线程模式,优先级等。 注意订阅和取消订阅的生命周期。
- 发送消息体。
1、定义消息事件
事件是普通的Java对象,没有任何特定的要求。例如:
public class MessageEvent {
public String message;
public MessageEvent(String message){
this.message = message;
}
}
2、准备订阅
在EventBus3.0之前,执行消息体的方法名是固定的,3.0之后方法方法名是用户随意定义,但需要用@Subscribe注解定义你的方法。如下面示例:
// 当发送MessageEvent消息时,该方法会执行 (指定在UI线程中)
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(MessageEvent event) {
Toast.makeText(getActivity(), event.message, Toast.LENGTH_SHORT).show();
}
// 当发送SomeOtherEvent消息时,执行该方法
@Subscribe
public void handleSomethingElse(SomeOtherEvent event) {
doSomethingWith(event);
}
注意订阅和取消订阅的生命周期,只有在该对象中订阅了,才会接受到消息并执行对应的方法。例如在常用的Activity和Fragment中根据其生命周期进行订阅和反订阅逻辑,一般在onCreate/onStop方法中进行订阅和取消订阅。
@Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
@Override
public void onStop() {
EventBus.getDefault().unregister(this);
super.onStop();
}
3、发送事件消息
在代码的任何部分都可以发布事件。 所有当前注册的匹配事件类型的订阅者都会收到它。
EventBus.getDefault().post(new MessageEvent("Hello everyone!"));
三、@Subscribe注解中可以指定的属性
消息事件可以发布在与发布线程不同的线程中, 一个常见的用例是处理UI更改。 在Android中,UI更改必须在UI(主)线程中完成。 另一方面,网络或任何耗时的任务不得在主线程上运行。 EventBus可以帮助您处理这些任务并与UI线程同步(无需深入研究线程转换,使用AsyncTask等)。
1、指定线程模式
- ThreadMode: POSTING
这是默认的模式,事件发布和处理在同一个线程中,事件传递是同步完成的,所有订阅者在发布完成后都会被调用。 这个ThreadMode意味着最小的开销,因为它避免了完全的线程切换。 因此,对于已知完成的简单任务而言,这是推荐的模式,只需很短的时间而不需要主线程。 使用此模式的事件处理程序应该快速返回以避免阻塞发布线程,该线程可能是主线程。 例:
// 这里的threadMode可写也可不写,默认在当前线程
@Subscribe(threadMode = ThreadMode.POSTING)
public void onMessage(MessageEvent event) {
log(event.message);
}
- ThreadMode: MAIN
订阅者将在Android的主线程(有时称为UI线程)中被调用。 如果发布线程是主线程,则会直接通过反射调用事件处理程序方法(与ThreadMode.POSTING中描述的同步)。 使用此模式的事件处理程序必须快速返回以避免阻塞主线程。 例:
// 在UI线程中执行
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessage(MessageEvent event) {
textField.setText(event.message);
}
- ThreadMode: MAIN_ORDERED
事件处理方法在主线程中执行,不过需要排队,需要等前一个执行完成后才执行。按队列顺序进行处理
// 在主线程中执行,有执行顺序
@Subscribe(threadMode = ThreadMode.MAIN_ORDERED)
public void onMessage(MessageEvent event) {
textField.setText(event.message);
}
- ThreadMode: BACKGROUND
订阅者将在后台线程中调用。 如果发布线程不是主线程,则会在发布线程中直接调用事件处理程序方法。 如果发布线程是主线程,则EventBus使用单个后台线程来按顺序发送所有事件。 使用此模式的事件处理程序应尽快返回以避免阻塞后台线程。
// 在非主线程中执行
@Subscribe(threadMode = ThreadMode.BACKGROUND)
public void onMessage(MessageEvent event){
saveToDisk(event.message);
}
- ThreadMode: ASYNC
事件处理程序方法在单独的线程中调用。 这总是独立于发布线程和主线程。 如果事件处理程序的执行可能需要一些时间,则它应该使用这种模式。 用于网络访问,避免同时触发大量长时间运行的异步处理程序方法来限制并发线程的数量。 EventBus使用线程池有效地重用已完成异步事件处理程序通知中的线程。
// 在单独的线程中执行
@Subscribe(threadMode = ThreadMode.ASYNC)
public void onMessage(MessageEvent event){
backend.send(event.message);
}
四、EventBus中的粘性消息事件
粘性事件简单讲就是,在事件消息发出去之后再订阅该事件也能收到该事件 ,即便事件已经在所有订阅者中传递完成了,如果此时再创建一个新的订阅者(如一个注册了该StickyEvent的Activity),则在订阅者启动后,会自动调用一次该订阅者的onEventXXX方法来处理该StickyEvent。
任何时候在任何一个订阅了该事件的订阅者中的任何地方(可以在任何函数中,而不仅仅是在onEventXXX方法中),都可以通过EventBus.getDefault().getStickyEvent(MyEvent.class)来取得该类型事件的最后一次缓存。同时,也可以在需要的时候,利用removeStickyEvent方法来移除对某种StickyEvent的缓存。
1、发送和注册
例 发送粘性事件信息:
EventBus.getDefault().postSticky(new MessageEvent("Hello everyone!"));
然后开启新的Activity,并进行注册,设置sticky = true 则表示会按粘性事件逻辑执行。
@Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
// UI updates must run on MainThread
@Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
public void onEvent(MessageEvent event) {
textField.setText(event.message);
}
@Override
public void onStop() {
EventBus.getDefault().unregister(this);
super.onStop();
}
2、手动获取和移除粘性事件最后的粘性事件会在注册时自动发送给匹配的订阅者。 但有时候手动检查粘性事件可能会更方便。 此外,可能需要删除(消耗)粘性事件,以使它们不再被传递。 例:
MessageEvent stickyEvent = EventBus.getDefault().getStickyEvent(MessageEvent.class);
// Better check that an event was actually posted before
if(stickyEvent != null) {
// "Consume" the sticky event
EventBus.getDefault().removeStickyEvent(stickyEvent);
// Now do something with it
}
EventBus.getDefault().removeStickyEvent()方法是重载的,接受两种类型的参数,一种是消息对象,一种是消息Class对象。如:
MessageEvent stickyEvent = EventBus.getDefault().removeStickyEvent(MessageEvent.class);
// Better check that an event was actually posted before
if(stickyEvent != null) {
// Now do something with it
}
总结:以上就是对EventBus的使用简析,希望有所帮助。