EventBus3的使用实战(一)
eventbus2学习参考:http://blog.youkuaiyun.com/lmj623565791/article/details/40794879
eventbus3与eventbus2的区别:
eventbus2,在接收事件的方法名上使用约定的命名,通过方法的名字判定是否是接收事件的方法,以及在哪个线程处理事件,因此使用eventbus2时,要注意接收事件方法的命名,eventbus3使用,接收方法命名可以随意起来,但是方法内参数要和发送事件的参数类型对应,通过注解来取代eventbus2的约定命名,这是eventbus2和eventbus3使用的主要区别,eventbus3中也添加了一些新的方法;
阅读本文需要对EventBus3有一定的了解,如不了解,可以先阅读这篇博客:http://blog.youkuaiyun.com/songdongwan/article/details/64244411
通过一个简单的例子来对EventBus3使用练习一下;
项目布局很简单,只是两个按钮,布局代码不帖出来了,通过两个按钮分别从UI线程和子线程post事件
post事件代码:
//从子线程post事件
mThreadBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
new Thread() {
@Override
public void run() {
EventBus.getDefault().post(new MyEvent());
Log.e("thread", "runnable" + Thread.currentThread());
}
}.start();
}
});
--------------------------------------------------
//从主线程post事件
mMainBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
EventBus.getDefault().post(new MyEvent());
}
});
注册和解除注册
@Override
protected void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
@Override
protected void onStop() {
super.onStop();
EventBus.getDefault().unregister(this);
}
事件处理代码:
@Subscribe(threadMode = ThreadMode.MAIN, priority = 1)
public void onHandleEvent1(MyEvent myEvent) {
myEvent.makeToast("sdongwan", this);
Log.e("thread", "onHandleEvent1: " + Thread.currentThread());
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onHandleEvent2(MyEvent myEvent) {
myEvent.makeToast("bcy", this);
Log.e("thread", "onHandleEvent2: " + Thread.currentThread());
}
@Subscribe(threadMode = ThreadMode.POSTING, priority = 2)
public void onHandleEvent3(MyEvent myEvent) {
//myEvent.makeToast("posting", this);
Log.e("thread", "onHandleEvent3: " + Thread.currentThread());
}
@Subscribe(threadMode = ThreadMode.BACKGROUND)
public void onHandleEvent4(MyEvent myEvent) {
Log.e("thread", "onHandleEvent4: " + Thread.currentThread());
}
@Subscribe(threadMode = ThreadMode.BACKGROUND)
public void onHandleEvent5(MyEvent myEvent) {
Log.e("thread", "onHandleEvent5: " + Thread.currentThread());
}
@Subscribe(threadMode = ThreadMode.ASYNC)
public void onHandleEvent6(MyEvent myEvent) {
Log.e("thread", "onHandleEvent6: " + Thread.currentThread());
}
@Subscribe(threadMode = ThreadMode.ASYNC)
public void onHandleEvent7(MyEvent myEvent) {
Log.e("thread", "onHandleEvent7: " + Thread.currentThread());
}
- 点击一次子线程按钮,从子线程post事件,打印的log如下:
onHandleEvent3,onHandleEvent4,onHandleEvent5都在子线程中处理事件,并且在post事件的子线程中;
onHandleEvent6,onHandleEvent7在同一个线程池中的不同子线程处理事件;
onHandleEvent1,onHandleEvent2在主线程中,并且onHandleEvent1先被调用;
- 点击一次main线程按钮,从UI线程中post事件,打印的log如下:
onHandleEvent1,onHandleEvent2,onHandleEvent3都在主线程中;
onHandleEvent4,onHandleEvent5在同一个线程池的相同线程中;
onHandleEvent6,onHandleEvent7在同一个线程池的不同线程中;
从上面可以得出:
priority 优先级越大,越先回调事件处理方法,这个例子中onHandleEvent3优先级最大为2,其次onHandleEvent1的优先级为1,其他事件处理方法优先级默认为0,但从上面的图片中看到事件回调的顺序不是onHandleEvent3,接着onHandleEvent1,因为优先级只用于同一个mode来调整顺序,不同mode顺序无法根据优先级比较;
threadmode=ThreadMode.MAIN 在main线程中回调事件处理方法;
threadMode = ThreadMode.POSTING 如果post事件的线程是main线程,则在main线程中回调事件处理方法;如果post事件的线程是子线程,则在post事件的线程中回调事件处理方法,简而言之,就是在post事件的线程中回调事件处理方法;
threadMode = ThreadMode.BACKGROUND 如果post事件的线程是main线程,则在线程池中找出一条线程,用来当作background线程,其他的ThreadMode.BACKGROUND事件处理方法全部在这个background线程中回调;如果post事件的线程是子线程,则在post事件的线程中回调事件处理方法,总之,background线程肯定是子线程,且只有一个background线程;
threadMode = ThreadMode.ASYNC 不管post事件的线程是main线程还是子线程,这个mode下的事件处理方法回调在单独的子线程中,每个事件处理方法独享一个子线程,由于eventbus底层用线程池,所以也就是同一个线程池的不同线程;
配置EventBus3
在MyApplication中配置EventBus3
public class MyApplication extends Application {
public static EventBus eventBus;
@Override
public void onCreate() {
super.onCreate();
//1
EventBus.builder().throwSubscriberException(false).installDefaultEventBus();// 捕获异常,程序不会奔溃;
//2
//EventBus.builder().throwSubscriberException(true).installDefaultEventBus();//未捕获异常,程序奔溃;
//3
// EventBus.builder()
// .logNoSubscriberMessages(true)
// .sendNoSubscriberEvent(true)
// .installDefaultEventBus();
//4
// EventBus.builder()
// .logNoSubscriberMessages(false)
// .sendNoSubscriberEvent(false)
// .installDefaultEventBus();
}
}
- 在My Application中配置 1 代码,代码的意义是:当事件处理方法中抛出异常时,由eventbus捕获异常,处理异常,app不会奔溃;可以自己写个订阅者来处理异常,方法参数类型为SubscriberExceptionEvent
@Subscribe
public void onCatchError(SubscriberExceptionEvent subscriberExceptionEvent){
Log.e("thread", "onCatchError: "+subscriberExceptionEvent.toString() );
}
在My Application中配置 2 代码,代码意义是:不捕获异常信息,直接抛出异常,app奔溃,此时自己无法处理异常;
在My Application中配置 3 代码,一开始我没有看懂这是什么意思,有什么作用,查看源码后,才发现它的作用;源码如下:
//EventBus.java源码中postSingleEvent方法片段
if (logNoSubscriberMessages) {
Log.d(TAG, "No subscribers registered for event " + eventClass);
}
if (logNoSubscriberMessages && eventClass != NoSubscriberEvent.class &&
eventClass != SubscriberExceptionEvent.class) {
post(new NoSubscriberEvent(this, event));
}
我们在builder中设置logNoSubscriberMessages(false)和sendNoSubscriberEvent(false)只是设置对应的变量bool值,当logNoSubscriberMessages为true,会打印一段日志,当logNoSubscriberMessages为true,以及事件类型不是event.class和SubscriberExceptionEvent.class时,就会post一个事件,参数类型为NoSubscriberEvent;
我们新添加一个订阅者,用来处理NoSubscriberEvent事件:
@Subscribe
public void onHandleEvent7(NoSubscriberEvent n) {
Log.e("thread", "onHandleEvent7: " + Thread.currentThread() +n.toString());
}
事件处理中打印出一段日志,当我们把匹配post事件类型(MyEvent)的订阅者注释掉后,重新post事件,运行结果如下:
可以发现,打印出一段日志,以及我们自己的事件处理,可以通过这个方法来对没有匹配类型的事件进行处理;
- 在My Application中配置 4 代码,不会打印日志,不会回调NoSubscriberEvent事件处理;
注意:当我们post出一个类型事件,没有相应类型的订阅者来处理,eventbus3中会app奔溃,报错:
MainActivity and its super classes have no public methods with the @Subscribe annotation
EventBus3默认会post出NoSubscriberEvent事件,只要我们书写了NoSubscriberEvent类型的订阅者,自己处理事件后,程序就不会奔溃;
下一篇将介绍EventBus sticky event的使用,以及其他的方面;
如有不对的地方,欢迎大家留言指出。。。。