在实际的开发中呢我们经常会遇到很多的页面间的信息传递,有时会用到broadcastReceiver和startActivityForResult(),这些方式在实际运用中造成了大量的代码重复操作和不便的管理性,这时EventBus就可以闪亮登场了。
按照惯例我们首先放上EventBus在GitHub上的链接,我们先看一张来自官方给我们的一个图,这个能很好的认知。
从图中我们可以看出EventBus的简单的一个流程,首先由Publisher post一个Event并将Event保存到EventBus中然后再将Event交由具体的订阅者进行订阅处理,那么我们在具体的应用中需要做的是什么呢首先我们需要发布一个事件,然后需要注册一个方法订阅这个事件并处理这个事件。
在EventBus中有2种事件分别是普通事件和粘性事件。这里我们先说下应用场景,如果说我们需要后面的页面返回信息,那么我们可以用普通事件,如果说我们需要向后面的页面传递信息,这个时候后面的页面还没初始化,那么我们只能用粘性事件了,那么对于普通事件的应用场景我们可以用粘性事件吗,答案是可以的。
普通事件是我需要先注册订阅事件,然后才可以发送事件,即A->B->A,我们需要先在A中注册订阅事件,在B中发送事件,然后回到A中我们才能在订阅事件中进行处理。粘性事件则是我们可以先发送事件,然后再订阅事件,这个时候在订阅事件才可以处理这个事件,对于粘性事件我们进行关闭操作,不再让这个事件进行再次传递,当然我们也可以不关闭。
接下来我们来写个Demo学习下如何使用
1.集成EventBus,在Android studio中,我们首先要导入EventBus3.1.1
implementation 'org.greenrobot:eventbus:3.1.1'
2.普通事件
2.1 Activity中首先注册EventBus
EventBus.getDefault().register(this);
既然我们已经注册了EventBus,基于这个我们需要在onDestroy()中进行反注册防止内存泄漏
EventBus.getDefault().unregister(this);
2.2 定义一个事件,在这个类中的信息我们可以自定义,即我们需要什么信息,都可以在这里给出
public class NormalEvent {
private int eventCode;
private String message;
}
这个类的构造方法、set、get、toString我就不贴了
2.3 注册订阅事件
@Subscribe()
public void receiveEvent(NormalEvent event){
tv.setText(event.toString());
Log.e("TAG", event.toString());
}
这里先说明个事情,防止大家产生疑惑,注解是必须的,注解里的内容我们先暂时不管这个,方法名是可以我们来随便写的,前提是你能在后面看的时候知道这个方法是做什么用的,还有一个更为重要的问题大家千万要记住在代码中的NormalEvent是我们自定义的一个事件,当我们在这里定义好了接受事件后,那么必然需要我们在发送事件时发送的是同一个事件。如果说我们有多个订阅事件方法,那么在实际的事件分发时是根据Event的类型来确定的。
2.4 发送事件
EventBus.getDefault().post(new NormalEvent(ContentUtils.NORMAL_EVENT_CODE,"This is a normal event"));
这是一个普通的事件,到这里我们已经发出去了。在订阅事件中我们也就可以接收到我们的事件了,我们也可以处理了。
3.粘性事件
3.1 定义一个事件,为了区分普通事件我们重新写一个吧
public class StickyEvent {
private int eventCode;
private String message;
}
3.2 发送一个事件
EventBus.getDefault().postSticky(new StickyEvent(ContentUtils.STICKY_EVENT_CODE,"This is a sticky event"));
是不是和发送普通事件差不多,后面我们再说,这后面发生了什么。
3.3 注册EventBus和反注册EventBus
EventBus.getDefault().register(this);
EventBus.getDefault().unregister(this);
这里和普通事件是一样的
3.4 注册订阅事件
@Subscribe(sticky = true)
public void receiveStickyEvent(StickyEvent event) {
mTextView.setText("粘性事件数据:" + event.toString());
Log.e("TAG", event.toString());
EventBus.getDefault().cancelEventDelivery(event);
}
这里和普通事件的注意事项一样,唯一不通的是我们在注解中说明了sticky = true,这句话告诉了EventBus,我们这里接收的是粘性事件。
到这里我们的普通事件和粘性事件就学完了。
接下来我们看下ThreadMode,这个同样是注解里的,通过设置参数来告诉订阅事件我们处理订阅事件的线程。
在新的3.1.1版本中我们发现ThreadMode中有5个模式分别是POSTING、MAIN、MAIN_ORDERED、BACKGROUND、ASYNC
ThreadMode是我们在使用过程中对接收事件的线程的规定
POSTING
就是说我们在发送事件时在哪个线程那么接受事件时就在哪个线程
MAIN
当是MAIN模式时无论我们发送事件在哪个线程,我们的处理事件方法都是在主线程执行的
MAIN_ORDERED
这个在我以前用的时候并没有这个,但是在3.1.1中发现了这个,我们可以理解为这个模式时 在Android上,用户将在Android的主线程(UI线程)中被调用。不同于MAIN,事件将始终排队等待传递。这确保了后调用是非阻塞的。
BACKGROUND
当是BACKGROUND模式时无论我们发送事件在哪个线程,我们的处理事件方法都是在子线程执行的
ASYNC
当是ASYNC模式时无论我们发送事件在哪个线程,我们的处理事件方法都不是在发送事件的线程
即当主线程发送时我们在子线程处理,子线程发送时在主线程处理
就来写写代码吧,来做些简单的线程切换,POSTING就不写了,我们来写下MAIN,至于MAIN_ORDERED,可能会在后面进行补充。
在子线程中发送事件,先不规定在哪个线程处理,即默认的POSTING,我们先来看下带代码
new Runnable() {
@Override
public void run() {
EventBus.getDefault().post(new NormalEvent(ContentUtils.NORMAL_EVENT_CODE, "切换到主线程"));
}
}.run();
@Subscribe()
public void receiveEvent(NormalEvent event){
Log.e("TAG", event.toString());
Log.e("TAG",Thread.currentThread().getName());
}
我们来看下打印结果
我们看到我们是咋子线程进行处理的,如果我们指定了线程呢?代码如下
@Subscribe(threadMode = ThreadMode.MAIN)
public void receiveEvent(NormalEvent event){
Log.e("TAG", event.toString());
Log.e("TAG",Thread.currentThread().getName());
}
我们可以看到这里我们已经切换到了主线程,BACKGROUND同样的道理。
好了到这里我们已经基本上会使用EventBus,祝大家工作愉快!