您的位置:首页 > 移动开发 > Android开发

Android开发学习之路-EventBus使用

2016-09-27 16:21 459 查看
EventBus是一个通过发布、订阅事件实现组件间消息传递的工具。

它存在的目的,就是为了优化组件之间传递消息的过程。传统组件之间传递消息的方法有使用广播,回调等,而这些方法使用都比较复杂。

工作原理:



依赖:

dependencies {
compile 'org.greenrobot:eventbus:3.0.0'
}


注:EventBus是事件-订阅模型,实际上事件就是消息,订阅就是接收,本文不会很严格区分,方便理解为主!

1. 从简单的入手:充当Handler

既然能发送消息,那么自然在同一个组件下也能进行消息的发送和接收,也就是Handler的职责。

先定义一个事件的对象:

public class MessageEvent {
private String message;

public MessageEvent(String message) {
this.message = message;
}

public String getMessage() {
return message;
}

@Override
public String toString() {
return message;
}
}


这个事件对象只需要是Object的子类,没其他要求,消息的内容可以随意定,这里用一个String表示事件的消息,toString直接输出事件的内容。

在需要接收消息的组件中,进行EventBus的绑定,这里由Activity充当订阅者(Subscriber),也就是消息接收者。

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}

@Override
protected void onStart() {
super.onStart();
EventBus.getDefault().register(this); // 将当前Activity绑定为订阅者
}

@Override
protected void onStop() {
EventBus.getDefault().unregister(this); // 解绑
super.onStop();
}

// 声明一个订阅方法,用于接收事件
@Subscribe
public void onEvent(MessageEvent messageEvent) {
Log.d(TAG, "onEvent() called with: messageEvent = [" + messageEvent + "]");
}

}


通过EventBus.getDefault方法获取到一个EventBus的一个单例,也就是每次调用这个方法得到的都是同一个EventBus对象。而不同的EventBus对象消息不会互通。

接着需要在Activity的onStart方法中进行对EventBus对象的绑定,在onStop方法中进行解绑。同时,需要定义用于接收事件的方法,并加上@Subscribe注解表明该方法用于接收订阅事件。

接着,我们需要发送事件:

EventBus.getDefault().post(new MessageEvent("I m Fndroid"));


这里获取的默认的EventBus对象,通过post方法进行事件的发送,log如下:



2. 组件间通讯:代替广播、回调等

EventBus的存在,并不是为了替代Handler,而是用来进行组件间的通讯。有了上面的知识,接下来就不难了。

我们都知道,只要是同一个EventBus对象绑定的组件(Subscriber),消息是互通的,也就是我们可以在Service中向Activity发送事件进行通讯。(其他组件类似)

定义一个IntentService,并且发送一个事件,而Activity,和上面一样。

public class MyIntentService extends IntentService {

public MyIntentService() {
super("MyIntentService");
}

@Override
protected void onHandleIntent(Intent intent) {
EventBus.getDefault().post(new MessageEvent("From service"));
}

}


在Activity中开启服务:

startService(new Intent(this, MyIntentService.class));


Log:



组件间的通讯变得如此简单了。

3. 进阶:持久事件、线程模式、优先级

① 持久事件(StickyEvent):对于调用post方法发送的普通消息,会在第一次被接收到的时候被消费掉,也就是我们在@Subscribe方法下处理完了,这个消息就消失了。而EventBus则提供了另一种类型的消息——StickyEvent,这个消息,会被保存在RAM中,直到下一个StickyEvent被发送才会被替换。每个EventBus对象都能通过geStickyEvent方法获取最近发出的持久事件。

我们对Activity稍作修改,在订阅方法中,把当前的持久消息打印出来:

// 声明一个订阅方法,用于接收事件
@Subscribe
public void onEvent(MessageEvent messageEvent) {
Log.d(TAG, "onEvent() called with: messageEvent = [" + messageEvent + "]");
Log.d(TAG, "onEvent: Sticky Event = [" + EventBus.getDefault().getStickyEvent(MessageEvent.class) + "]");
}


接着对Service也进行修改,令其发送一个StickyEvent:

@Override
protected void onHandleIntent(Intent intent) {
EventBus.getDefault().post(new MessageEvent("From service"));
EventBus.getDefault().postSticky(new MessageEvent("From service2"));
EventBus.getDefault().post(new MessageEvent("From service3"));
}


这里看到,在第二次发送的时候,调用了postSticky方法发送事件,这就表明了该事件是一个持久事件,除非有新的同类型(不同类型的事件可以共存)持久事件被发送,否则会一直被保存在内存中,我们任何时候都能获取得到。

Log:



可以看到,在第三次接收到消息的时候,将StickyEvent打印出来,依旧是"From service2"。

同样的,如果我们想要移除此持久事件,可以调用EventBus的removeStickyEvent方法来实现,如果要移除所有类型的持久事件,可以调用removeAllStickyEvent方法。

② 线程模式

EventBus允许我们对订阅者进行线程设置,默认情况下,订阅是和事件发送处于同一线程的,我们不妨把订阅的线程id打印出来看一看。

修改Activity中的@Subscribe方法:

@Subscribe
public void onEvent(MessageEvent messageEvent) {
Log.d(TAG, "onEvent: Thread id = [" + Thread.currentThread().getId() + "]");
Log.d(TAG, "onEvent() called with: messageEvent = [" + messageEvent + "]");
}


修改Service,让其发送一次普通事件,并且输出当前线程id:

@Override
protected void onHandleIntent(Intent intent) {
Log.d(TAG, "onHandleIntent: Thread id = [" + Thread.currentThread().getId() + "]");
EventBus.getDefault().post(new MessageEvent("From service"));
}


打印Log:



对于订阅者,有以下四种线程模式:

POSTING:默认模式,订阅和事件发送在同一线程下进行

MAIN:订阅在主线程下进行,可以直接修改UI

BACKGROUND:如果事件发送在主线程,则订阅在子线程下进行,如果事件发送在子线程,则订阅也在该子线程中进行

ASYNC:如果事件发送在主线程,则订阅在子线程下进行,如果事件发送在子线程,则订阅会在其他子线程中进行

设置订阅者线程很简单,只需要在注解中赋值即可,如:

@Subscribe(threadMode = ThreadMode.MAIN)


③ 优先级

每个组件中可以有多个订阅方法,而我们可以对它们设置不同的优先级,设置的方法也很简单:

@Subscribe(priority = 88)


默认的优先级为0,更高优先级的订阅方法会更先收到事件,而每个订阅方法都可以对事件进行终止,可以通过以下方法停止事件传递:

EventBus.getDefault().cancelEventDelivery(messageEvent);


④ 自定义EventBus对象

通过getDefault方法获取的是一个EventBus默认的单例,而我们可以通过EventBus.Builder来构造一个自定义的EventBus对象。

明白了用法以后,我们分析源码也会更加简单。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: