介绍
1.什么是EventBus
想必每个入了门的Android开发者都多少对EventBus有过了解,EventBus是一个Android事件发布/订阅框架,通过解耦发布者和订阅者简化 Android 事件传递。
EventBus 直译过来就是事件总线,它使用发布订阅模式支持组件之间的通信,不需要显式地注册回调,比观察者模式更灵活,可用于替换Java中传统的事件监听模式,EventBus的作用就是解耦,它不是通用的发布订阅系统,也不能用于进程间通信。
最近EventBus刚好更新了3.0版本,事件的订阅已经从方法名换成了注解的方式。3.0版本将粘性事件以及订阅事件的优先级换了一种更好的实现方式,所以3.0版本中的注册就变得简单,只有一个register()
方法即可.
使用 EventBus3.0
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
EventBus.getDefault().register(this);
}
public void onEventBus(View view) {
EventBus.getDefault().post(new Student(12, "helen"));
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEvenHaha(Student student) {
Log.d(TAG, "ThreadMode.MAIN:thread info:" + Thread.currentThread() + ",bean info:" + student.toString());
}
@Subscribe(threadMode = ThreadMode.POSTING)
public void onEventPost(Student student) {
Log.i(TAG, "ThreadMode.POSTING:thread info:" + Thread.currentThread() + ",bean info:" + student.toString());
}
@Subscribe(threadMode = ThreadMode.BACKGROUND)
public void onEventBackground(Student student) {
Log.w(TAG, "ThreadMode.BACKGROUND:thread info:" + Thread.currentThread() + ",bean info:" + student.toString());
}
@Subscribe(threadMode = ThreadMode.ASYNC)
public void onEventAsyn(Student student) {
Log.e(TAG, "ThreadMode.ASYNC:thread info:" + Thread.currentThread() + ",bean info:" + student.toString());
}
@Override
protected void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
}
post一个obj,在ui线程。结合文档ThreadMode.java 的说明,可以知道:
原理概述
EventBus解耦的方式其实是使用了反射,我在调用register()方法的时候,获取到Subscription对象,EventBus就扫描调用Subscription类,将需要反射调用的方法信息记录下来,这些方法就是
onEvent(),
onEventMainThread(),
onEventBackgroundThread()
onEventAsync()。
这些方法被记录以后,如果有人调用post()方法,就会在记录里面查找,然后使用反射去触发这些方法。反射触发方法的方式是调用Method类的invoke()方法。
public Object invoke(Object obj, Object... args)
显然要我们需要1,Method对象,订阅者对象obj,还有参数对象args
也就是说记录里面,对应一个订阅方法,起码要有上面三个参数。
- 我们在register()的时候,目的是获得Subscription对象
- 我们在post(Object obj)的时候,目的是将传入的obj和相应的Subscription对象一起封装成PendingPost对象
将其放入队列里面排队,队列会不断取出元素,触发反射!
扫描方法
你只要记得一件事:扫描了所有的方法,把匹配的方法最终保存在subscriptionsByEventType(Map,key:eventType ; value:CopyOnWriteArrayList<Subscription> )中;
eventType是我们方法参数的Class
Subscription中则保存着subscriber, subscriberMethod(method, threadMode, eventType), priority;包含了执行改方法所需的一切。