本文的源码使用到EventBus3.2.0版本
本文所示的源码将会忽略与核心逻辑无关的代码,被忽略的代码将使用省略号表示
以下为eventBus最简单的使用代码:
public class TestActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
// 注册eventbus
EventBus.getDefault().register(this);.
// 发送消息
EventBus.getDefault().post(new Object());
}
// 添加消息监听注解
@Subscribe()
public void onEvent(Event event){
Log.d("test","接收到消息");
}
}
该代码运行后将会打印,“接收到消息”;
EventBus注册原理
那么接下来分析代码“EventBus.getDefault().register(this)”,干了什么
public void register(Object subscriber) {
// 获取订阅者的class对像
Class<?> subscriberClass = subscriber.getClass();
// 获取所有带有注解“@Subscribe”的方法
List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
...
}
我们继续进入“subscriberMethodFinder.findSubscriberMethods(subscriberClass)”方法中:
List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
...
if (ignoreGeneratedIndex) {
//默认走这里
subscriberMethods = findUsingReflection(subscriberClass);
} else {
subscriberMethods = findUsingInfo(subscriberClass);
}
....
}
// 命名知意,使用反射方式查找
private List<SubscriberMethod> findUsingReflection(Class<?> subscriberClass) {
FindState findState = prepareFindState();
...
findUsingReflectionInSingleClass(findState);
...
return getMethodsAndRelease(findState);
}
private void findUsingReflectionInSingleClass(FindState findState) {
Method[] methods;
...
// 获取订阅者对象的所有方法
methods = findState.clazz.getDeclaredMethods();
...
//遍历所有方法
for (Method method : methods) {
...
// 核心!核心!核心!
Class<?>[] parameterTypes = method.getParameterTypes();
// 过滤只有一个参数的方法
if (parameterTypes.length == 1) {
Subscribe subscribeAnnotation = method.getAnnotation(Subscribe.class);
// 找出带有“Subscribe”注解的方法
if (subscribeAnnotation != null) {
Class<?> eventType = parameterTypes[0];
if (findState.checkAdd(method, eventType)) {
ThreadMode threadMode = subscribeAnnotation.threadMode();
// 新建一个订阅者方法对象,并缓存到subscriberMethods队列中
findState.subscriberMethods.add(new SubscriberMethod(method, eventType, threadMode,
subscribeAnnotation.priority(), subscribeAnnotation.sticky()));
}
}
}
...
}
}
好了,简单来说,EventBus注册其实就是找出被注册对象中所有带有@Subscribe注解的方法,并缓存起来!
EventBus发送消息原理
我们一起来看看 "EventBus.getDefault().post(new Object())"干了什么
public void post(Object event) {
PostingThreadState postingState = currentPostingThreadState.get();
List<Object> eventQueue = postingState.eventQueue;
// 将消息加入到队列中
eventQueue.add(event);
...
while (!eventQueue.isEmpty()) {
// 遍历队列,并执行postSingleEvent
postSingleEvent(eventQueue.remove(0), postingState);
}
...
}
}
private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {
// 获取event的class对象,本事例是Object,实际使用将会是自定义的一个实体类
Class<?> eventClass = event.getClass();
... //剔除了所有非核心代码
// lookupAllEventTypes方法实际是找出event对象的所有基类,这里不多介绍,有兴趣的自己跟源码
List<Class<?>> eventTypes = lookupAllEventTypes(eventClass);
int countTypes = eventTypes.size();
for (int h = 0; h < countTypes; h++) {
Class<?> clazz = eventTypes.get(h);
subscriptionFound |= postSingleEventForEventType(event, postingState, clazz);
}
...
}
// 核心!核心!核心
private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class<?> eventClass) {
CopyOnWriteArrayList<Subscription> subscriptions;
synchronized (this) {
// 根据event对象,获取所有订阅者方法
subscriptions = subscriptionsByEventType.get(eventClass);
}
if (subscriptions != null && !subscriptions.isEmpty()) {
//遍历
for (Subscription subscription : subscriptions) {
...
postToSubscription(subscription, event, postingState.isMainThread);
...
}
return true;
}
return false;
}
private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {
// 忽略各种线程调度代码
...
invokeSubscriber(subscription, event);
...
}
//最终到这里
void invokeSubscriber(Subscription subscription, Object event) {
...
// 反射执行订阅者的方法,并传递event对象
subscription.subscriberMethod.method.invoke(subscription.subscriber, event);
...
}
所以,简单来说,EventBus消息发送就是通过event对象找出在注册时所缓存的订阅者方法,然后执行!
原理总结
一句话,注册就是以反射方式缓存订阅者方法,发送消息就是以反射方式执行已缓存的订阅者方法。
核心实现原理仅用到Java反射机制!
OK,就这么多!用帮助的话,点个赞!