分析下边代码
// Activity中注册反注册
EventBus.getDefault().register(this);
EventBus.getDefault().unregister(this);
// Activity中用于接收数据写的方法
public void onEventMainThread()
// 发送数据的页面
EventBus.getDefault().post(param);
1. register
EventBus.getDefault()是一个单例
// 双重校验锁,防止并发,提高效率
public static EventBus getDefault() {
if (defaultInstance == null) {
synchronized (EventBus.class) {
if (defaultInstance == null) {
defaultInstance = new EventBus();
}
}
}
return defaultInstance;
}
register方法:
private synchronized void register(Object subscriber, String methodName, boolean sticky, int priority) {
// 调用 SubscriberMethodFinder类中的 findSubscriberMethods方法,
// 传入 this,methodName,返回一个 List<SubscriberMethod> subscriberMethods
List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriber.getClass(),
methodName);
// for循环扫描到的 方法,然后调用 subscribe,SubscriberMethod 中保存了
// method、threadMode、eventType,通过上边方法已经分析
for (SubscriberMethod subscriberMethod : subscriberMethods) {
subscribe(subscriber, subscriberMethod, sticky, priority);
}
}
subscriber:扫描的类,就是register(this)中的this;
methodName:写死的 onEvent,扫描该类中以 onEvent开头的方法;
sticky:
priority:优先级
调用 SubscriberMethodFinder 类中的 findSubscriberMethods方法,传入this,methodName,返回一个 List<SubscriberMethod> subscriberMethods,
// 遍历该类所有方法,根据 methodName 去匹配,匹配成功的 封装成 SubscriberMethod,然后返回 一个 List
List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass, String eventMethodName) {
String key = subscriberClass.getName() + '.' + eventMethodName;
List<SubscriberMethod> subscriberMethods;
synchronized (methodCache) {
subscriberMethods = methodCache.get(key);
}
if (subscriberMethods != null) {
return subscriberMethods;
}
subscriberMethods = new ArrayList<SubscriberMethod>();
Class<?> clazz = subscriberClass;
HashSet<String> eventTypesFound = new HashSet<String>();
StringBuilder methodKeyBuilder = new StringBuilder();
while (clazz != null) {
String name = clazz.getName();
if (name.startsWith("java.") || name.startsWith("javax.") || name.startsWith("android.")) {
// Skip system classes, this just degrades performance
break;
}
// 获取该类所有的方法
Method[] methods = clazz.getMethods();
// 遍历所有方法
for (Method method : methods) {
String methodName = method.getName();
// 判断是否以 onEvent开头、是否是public、且不是static和abstract,是否是1个参数
// 如果都符合,就封装
if (methodName.startsWith(eventMethodName)) {
int modifiers = method.getModifiers();
if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) {
Class<?>[] parameterTypes = method.getParameterTypes();
if (parameterTypes.length == 1) {
String modifierString = methodName.substring(eventMethodName.length());
ThreadMode threadMode;
if (modifierString.length() == 0) {
// 根据方法的后缀,确定threadMode,是枚举类型
threadMode = ThreadMode.PostThread;
} else if (modifierString.equals("MainThread")) {
threadMode = ThreadMode.MainThread;
} else if (modifierString.equals("BackgroundThread")) {
threadMode = ThreadMode.BackgroundThread;
} else if (modifierString.equals("Async")) {
threadMode = ThreadMode.Async;
} else {
if (skipMethodVerificationForClasses.containsKey(clazz)) {
continue;
} else {
throw new EventBusException("Illegal onEvent method, check for typos: " + method);
}
}
Class<?> eventType = parameterTypes[0];
methodKeyBuilder.setLength(0);
methodKeyBuilder.append(methodName);
methodKeyBuilder.append('>').append(eventType.getName());
String methodKey = methodKeyBuilder.toString();
if (eventTypesFound.add(methodKey)) {
// 这里将 method、threadMode、eventType传入构造方法,
// 封装成 SubscriberMethod,添加到list集合,然后返回
subscriberMethods.add(new SubscriberMethod(method, threadMode, eventType));
}
}
} else if (!skipMethodVerificationForClasses.containsKey(clazz)) {
Log.d(EventBus.TAG, "Skipping method (not public, static or abstract): " + clazz + "."
+ methodName);
}
}
}
// 扫描所有父类,并不是当前类
clazz = clazz.getSuperclass();
}
if (subscriberMethods.isEmpty()) {
throw new EventBusException("Subscriber " + subscriberClass + " has no public methods called "
+ eventMethodName);
} else {
synchronized (methodCache) {
methodCache.put(key, subscriberMethods);
}
return subscriberMethods;
}
}
继续 register中的方法,for 循环 扫描到的所有方法,然后调用 subscribe
for (SubscriberMethod subscriberMethod : subscriberMethods) {
subscribe(subscriber, subscriberMethod, sticky, priority);
}
private final Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType;
// Must be called in synchronized block
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod, boolean sticky, int priority) {
subscribed = true;
Class<?> eventType = subscriberMethod.eventType;
// 根据 subscriberMethod.eventType ,在 subscriptionsByEventType 中查找
// CopyOnWriteArrayList<Subscription>,如果没有则创建
// subscriptionsByEventType 是 Map集合,用于存储EventBus所有方法的地方
// key: eventType,value: CopyOnWriteArrayList<Subscription>
CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
// 把 传入的参数封装成 Subscription(subscriber, subscriberMethod, priority) 对象
Subscription newSubscription = new Subscription(subscriber, subscriberMethod, priority);
if (subscriptions == null) {
subscriptions = new CopyOnWriteArrayList<Subscription>();
subscriptionsByEventType.put(eventType, subscriptions);
} else {
for (Subscription subscription : subscriptions) {
if (subscription.equals(newSubscription)) {
throw new EventBusException("Subscriber " + subscriber.getClass() + " already registered to event "
+ eventType);
}
}
}
// Starting with EventBus 2.2 we enforced methods to be public (might change with annotations again)
// subscriberMethod.method.setAccessible(true);
int size = subscriptions.size();
for (int i = 0; i <= size; i++) {
if (i == size || newSubscription.priority > subscriptions.get(i).priority) {
// 添加 newSubscription,优先级高的 添加到 list集合前边
subscriptions.add(i, newSubscription);
break;
}
}
List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);
if (subscribedEvents == null) {
subscribedEvents = new ArrayList<Class<?>>();
typesBySubscriber.put(subscriber, subscribedEvents);
}
// 根据 subscriber 存储 所有的 eventType
// subscribedEvents是 Map 集合,key:subscriber value: List<eventType>
subscribedEvents.add(eventType);
// 判断 sticky:如果为true,从 stickyEvents 中 根据 eventType查找有没有 stickyEvent
// stickyEvent 就是 post(javabean)中传递的参数,
// 如果有就调用 postToSubscription,发布
if (sticky) {
Object stickyEvent;
synchronized (stickyEvents) {
stickyEvent = stickyEvents.get(eventType);
}
if (stickyEvent != null) {
// If the subscriber is trying to abort the event, it will fail (event is not tracked in posting state)
// --> Strange corner case, which we don't take care of here.
postToSubscription(newSubscription, stickyEvent, Looper.getMainLooper() == Looper.myLooper());
}
}
}
分析:
1>:首先根据 subscriberMethod.eventType,在 subscriptionsByEventType 中查找 CopyOnWriteArrayList<Subscription>,没有就创建;
subscriptionsByEventType 是一个Map集合,用于存储 EventBus 所有的方法,
key: eventType,value: CopyOnWriteArrayList<Subscription>;
2>:然后把 传入的 参数 封装成 Subscription(subscriber, subscriberMethod, priority) 对象;
3>:然后添加 上边的对象 newSubscription ,根据 优先级 添加到 list集合
register结论:扫描该类中所有的方法,把匹配的方法保存到subscriptionsByEventType(Map,key:eventType,value:CopyOnWriteArrayList<Subscription>)
eventType:就是post(Javabean)数据类型,
Subscription保存了 subscriber、subscriberMethod(method,threadMode,eventType,priority,sticky)
2. post
register:把所有方法存储到subscriptionsByEventType,post就是从该Map集合中取方法,然后调用
public void post(Object event) {
// currentPostingThreadState:ThreadLocal类型的,里边存储的 PostingThreadState
// PostingThreadState 包含:eventQueue队列 和 一些标志位
PostingThreadState postingState = currentPostingThreadState.get();
List<Object> eventQueue = postingState.eventQueue;
// eventQueue队列:用于保存 post 传入的event,其实就是 post传入过来的 javabean数据
eventQueue.add(event);
if (!postingState.isPosting) {
// 判断是否是主线程,
postingState.isMainThread = Looper.getMainLooper() == Looper.myLooper();
postingState.isPosting = true;
if (postingState.canceled) {
throw new EventBusException("Internal error. Abort state was not reset");
}
try {
// 遍历队列中存储的所有的 event,调用 下边的方法,
while (!eventQueue.isEmpty()) {
postSingleEvent(eventQueue.remove(0), postingState);
}
} finally {
postingState.isPosting = false;
postingState.isMainThread = false;
}
}
}
// currentPostingThreadState 是 ThreadLocal 类型的,用于存储 PostingThreadState
private final ThreadLocal<PostingThreadState> currentPostingThreadState = new ThreadLocal<PostingThreadState>() {
@Override
protected PostingThreadState initialValue() {
return new PostingThreadState();
}
};
final static class PostingThreadState {
// eventQueue
final List<Object> eventQueue = new ArrayList<Object>();
// 下边是一些标志位
boolean isPosting;
boolean isMainThread;
Subscription subscription;
Object event;
boolean canceled;
}
post:就是把event,其实就是传入的 Javabean数据 , 保存在当前线程的 PostingThreadState 的 eventQueue队列 中
1>:首先:判断当前是否是主线程;
2>:然后:遍历 eventQueue队列中所有的 event,其实就是遍历所有 post(param) 中传递的参数,然后调用 postSingleEvent
private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {
// 获取当前 Javabean数据 所在的 Class对象
Class<? extends Object> eventClass = event.getClass();
// 根据eventClass获取 List<Class<?>>,其实就是 Javabean数据 的当前Class、
// 及父类和接口的Class类型,用于匹配
// eventTypes:是所有 Class
List<Class<?>> eventTypes = findEventTypes(eventClass);
boolean subscriptionFound = false;
// 遍历所有Class,在 subscriptionsByEventType中 查找 subscriptions ,
// register注册:就是把 所有方法都存储到 subscriptionsByEventType集合中
int countTypes = eventTypes.size();
for (int h = 0; h < countTypes; h++) {
Class<?> clazz = eventTypes.get(h);
CopyOnWriteArrayList<Subscription> subscriptions;
synchronized (this) {
subscriptions = subscriptionsByEventType.get(clazz);
}
if (subscriptions != null && !subscriptions.isEmpty()) {
// 遍历每个 subscription ,依次调用 postToSubscription
for (Subscription subscription : subscriptions) {
postingState.event = event;
postingState.subscription = subscription;
boolean aborted = false;
try {
postToSubscription(subscription, event, postingState.isMainThread);
aborted = postingState.canceled;
} finally {
postingState.event = null;
postingState.subscription = null;
postingState.canceled = false;
}
if (aborted) {
break;
}
}
subscriptionFound = true;
}
}
if (!subscriptionFound) {
if (eventClass != NoSubscriberEvent.class && eventClass != SubscriberExceptionEvent.class) {
post(new NoSubscriberEvent(this, event));
}
}
}
分析postSingleEvent:
1>首先:获取当前 Javabean 数据所在的 Class对象,根据 该 对象获取 List<Class<?>>,这个就是 Javabean 数据 当前 Class及父类和接口的Class类型,用于匹配;
2>然后:遍历onEventMainThread(参数)中参数的所有 Class,在 subscriptionsByEventType中 查找 subscriptions,register注册时就是把 所有方法都存储到 subscriptionsByEventType集合中;
3>然后:然后 遍历每个 subscription,依次调用 postToSubscription,这个就是反射执行的方法,register时的 if(sticky) 就执行这个方法
private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {
switch (subscription.subscriberMethod.threadMode) {
case PostThread:
invokeSubscriber(subscription, event);
break;
case MainThread:
if (isMainThread) {
invokeSubscriber(subscription, event);
} else {
mainThreadPoster.enqueue(subscription, event);
}
break;
case BackgroundThread:
if (isMainThread) {
backgroundPoster.enqueue(subscription, event);
} else {
invokeSubscriber(subscription, event);
}
break;
case Async:
asyncPoster.enqueue(subscription, event);
break;
default:
throw new IllegalStateException("Unknown thread mode: " + subscription.subscriberMethod.threadMode);
}
}
根据threadMode判断,应该在哪个线程调用 反射方法
case PostThread:在当前线程,调用反射;
case MainThread:如果是主线程,则调用反射,否则用 handler发送消息,然后执行;
case BackgroundThread:如果是主线程,将任务加入到后台队列中,然后由EventBus中的一个线程池调用,如果是子线程,则直接调用反射;
case Async:与BackgroundThread一样,把任务加入到后台队列中,由EventBus中的一个线程池调用;且二者是同一个线程池;
BackgroundThread 与 Async区别:
BackgroundThread :它里边的任务一个接一个调用,中间用 boolean类型变量 handlerActive控制;
Async:动态控制并发;
3. 总结
register把当前类中 匹配的方法存储到一个 map集合中,post 根据传入的参数到map集合查找然后反射调用