前言
EventBus:
是一个针对Android进行了优化的发布/订阅事件总线。
github对应地址:EventBus
大家肯定都已经比较熟悉了,这里重点进行源码分析;
EventBus源码解析
我们重点从以下三个方法入手,弄清楚register
、unregister
以及post
方法,自然就能够明白EventBus
的工作原理;
EventBus.getDefault().register
public void register(Object subscriber) {
...
Class<?> subscriberClass = subscriber.getClass();
1.获取subscriberMethods集合;
List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
synchronized (this) {
for (SubscriberMethod subscriberMethod : subscriberMethods) {
2.进行事件订阅;
subscribe(subscriber, subscriberMethod);
}
}
}
我们可以看出register
方法主要做了如下两件事:
- 获取subscriberMethods集合;
- 进行事件订阅;
- 我们先分析第一步,
subscriberMethodFinder.findSubscriberMethods(subscriberClass);
private static final Map<Class<?>, List<SubscriberMethod>> METHOD_CACHE = new ConcurrentHashMap<>();
List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
//1.首先从缓存中取,METHOD_CACHE是一个ConcurrentHashMap,以subscriberClass为key,List<SubscriberMethod>为value
List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);
if (subscriberMethods != null) {
return subscriberMethods;
}
//ignoreGeneratedIndex属性表示是否忽略注解器生成的MyEventBusIndex,默认为false,为apt自动生成代码,这里跟踪反射处理代码,重点跟下findUsingReflection(subscriberClass)
if (ignoreGeneratedIndex) {
subscriberMethods = findUsingReflection(subscriberClass);
} else {
subscriberMethods = findUsingInfo(subscriberClass);
}
if (subscriberMethods.isEmpty()) {
throw new EventBusException("Subscriber " + subscriberClass
+ " and its super classes have no public methods with the @Subscribe annotation");
} else {
METHOD_CACHE.put(subscriberClass, subscriberMethods);
return subscriberMethods;
}
}
我们继续看下findUsingReflection(subscriberClass)
private List<SubscriberMethod> findUsingReflection(Class<?> subscriberClass) {
FindState findState = prepareFindState(); //这里使用了享元设计模式,从缓存池中取出FindState对象
findState.initForSubscriber(subscriberClass);
while (findState.clazz != null) {
findUsingReflectionInSingleClass(findState);
findState.moveToSuperclass();
}
return getMethodsAndRelease(findState);
}
继续分析findUsingReflectionInSingleClass(findState);
private void findUsingReflectionInSingleClass(FindState findState) {
Method[] methods;
try {
1.findState.clazz即为register入参clazz,可理解为activityClazz
首先反射获取activityClazz中的所有方法
methods = findState.clazz.getDeclaredMethods();
} catch (Throwable th) {
...
}
2.遍历所有方法,过滤是public方法
for (Method method : methods) {
int modifiers = method.getModifiers();
if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) { 3.获取方法对应参数clazz
Class<?>[] parameterTypes = method.getParameterTypes();
4.方法参数个数必须为1个
if (parameterTypes.length == 1) {
5.解析Subscribe注解
Subscribe subscribeAnnotation = method.getAnnotation(Subscribe.class);
if (subscribeAnnotation != null) {
Class<?> eventType = parameterTypes[0];
if (findState.checkAdd(method, eventType)) {
ThreadMode threadMode = subscribeAnnotation.threadMode();
6.将方法名、参数clazz、注解对应的threadmode、priority、sticky包装成SubscriberMethod对象并保存到findState.subscriberMethods中;
findState.subscriberMethods.add(new SubscriberMethod(method, eventType, threadMode,
subscribeAnnotation.priority(), subscribeAnnotation.sticky()));
}
}
....
}
}
分析完了subscriberMethods集合的创建过程后,我们在看下subscribe(subscriber, subscriberMethod)都做了什么?
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
1.获取subscriberMethod.eventType,对应的就是subscribe注解方法入参的clazz
Class<?> eventType = subscriberMethod.eventType;
2.构造Subscription对象
Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
3.subscriptionsByEventType为HashMap类型,根据eventType获取subscriptions;
CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
4.以eventType为key,CopyOnWriteArrayList<Subscription>为value,保存Subscription数据到subscriptionsByEventType中
if (subscriptions == null) {
subscriptions = new CopyOnWriteArrayList<>();
subscriptionsByEventType.put(eventType, subscriptions);
} else {
if (subscriptions.contains(newSubscription)) {
throw new EventBusException("Subscriber " + subscriber.getClass() + " already registered to event "
+ eventType);
}
}
int size = subscriptions.size();
for (int i = 0; i <= size; i++) {
if (i == size || subscriberMethod.priority > subscriptions.get(i).subscriberMethod.priority) {
subscriptions.add(i, newSubscription);
break;
}
}
5.构建typesBySubscriber对象,typesBySubscriber是为subscriber为key【可以理解为activity对象】,subscribedEvents为value【存储注解方法参数clazz的集合】
List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);
if (subscribedEvents == null) {
subscribedEvents = new ArrayList<>();
typesBySubscriber.put(subscriber, subscribedEvents);
}
subscribedEvents.add(eventType);
...
}
小结:
当调用register方法时,会通过反射(ignoreGeneratedIndex为true的情况下)解析注册对象所有的subscribe
注解方法(方法必须为public并且参数个数为1)保存到subscriberMethods
集合中,接着遍历subscriberMethods
集合,构建subscriptionsByEventType
和typesBySubscriber
的hashMap集合;
下面针对一些重要的对象中保存的数据进行简单的绘图:
SubscriberMethod
对象结构
SubscriptionsByEventType
对象结构
typesBySubscriber
对象结构
EventBus.getDefault().post
下面我们再看下发布事件
public void post(Object event) {
//currentPostingThreadState为ThreadLocal类,保证一个线程只有一份postingState
PostingThreadState postingState = currentPostingThreadState.get();
List<Object> eventQueue = postingState.eventQueue;
//1.将event添加到事件队列中
eventQueue.add(event);
if (!postingState.isPosting) {
postingState.isMainThread = isMainThread();
postingState.isPosting = true;
if (postingState.canceled) {
throw new EventBusException("Internal error. Abort state was not reset");
}
try {
//2.判断事件是不是正在post状态,不是的话不断遍历eventQueue,从前往后取event
while (!eventQueue.isEmpty()) {
postSingleEvent(eventQueue.remove(0), postingState);
}
} finally {
postingState.isPosting = false;
postingState.isMainThread = false;
}
}
}
postSingleEvent
最终会调用postSingleEventForEventType方法
private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class<?> eventClass) {
CopyOnWriteArrayList<Subscription> subscriptions;
synchronized (this) {
//1.根据post的数据类型clazz,从subscriptionsByEventType集合中获取subscriptions集合;
subscriptions = subscriptionsByEventType.get(eventClass);
}
if (subscriptions != null && !subscriptions.isEmpty()) {
2.遍历subscriptions集合,调用postToSubscription方法
for (Subscription subscription : subscriptions) {
postingState.event = event;
postingState.subscription = subscription;
boolean aborted;
try {
postToSubscription(subscription, event, postingState.isMainThread);
aborted = postingState.canceled;
} finally {
postingState.event = null;
postingState.subscription = null;
postingState.canceled = false;
}
if (aborted) {
break;
}
}
return true;
}
return false;
}
我们直接跟进postToSubscription
方法:
private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {
//根据threadMode属性分别执行不同逻辑;
switch (subscription.subscriberMethod.threadMode) {
case POSTING:
//如果是同一线程执行,直接执行invokeSubscriber
invokeSubscriber(subscription, event);
break;
case MAIN:
//如果是主线程执行,判断当前线程是否处于主线程中,不是的话通过Handler切换到主线程并调用invokeSubscriber
if (isMainThread) {
invokeSubscriber(subscription, event);
} else {
mainThreadPoster.enqueue(subscription, event);
}
break;
case MAIN_ORDERED:
//如果是主线程优先,主线程poster不为空,则调用主线程执行,否则直接执行invokeSubscriber
if (mainThreadPoster != null) {
mainThreadPoster.enqueue(subscription, event);
} else {
invokeSubscriber(subscription, event);
}
break;
case BACKGROUND:
//后台线程执行,如果是主线程调用线程池执行,否则直接执行invokeSubscriber
if (isMainThread) {
backgroundPoster.enqueue(subscription, event);
} else {
invokeSubscriber(subscription, event);
}
break;
case ASYNC:
//异步执行,直接通过线程池执行invokeSubscriber
asyncPoster.enqueue(subscription, event);
break;
default:
throw new IllegalStateException("Unknown thread mode: " + subscription.subscriberMethod.threadMode);
}
}
//实际上就是通过反射执行subscribe注解的方法
void invokeSubscriber(Subscription subscription, Object event) {
try {
subscription.subscriberMethod.method.invoke(subscription.subscriber, event);
} catch (InvocationTargetException e) {
handleSubscriberException(subscription, event, e.getCause());
} catch (IllegalAccessException e) {
throw new IllegalStateException("Unexpected exception", e);
}
}
小结:
调用post
方法,会根据post入参对象的clazz查找subscriptionsByEventType
集合拿到subscriptions【里面保存的有subscriber和subscribermethod】
,然后遍历subscriptions
集合,根据ThreadMode
执行不同的线程策略,最终均是通过反射执行subscribe注解的方法;
EventBus.getDefault().unregister
public synchronized void unregister(Object subscriber) {
List<Class<?>> subscribedTypes = typesBySubscriber.get(subscriber);
if (subscribedTypes != null) {
for (Class<?> eventType : subscribedTypes) {
unsubscribeByEventType(subscriber, eventType);
}
typesBySubscriber.remove(subscriber);
} else {
}
}
private void unsubscribeByEventType(Object subscriber, Class<?> eventType) {
List<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
if (subscriptions != null) {
int size = subscriptions.size();
for (int i = 0; i < size; i++) {
Subscription subscription = subscriptions.get(i);
if (subscription.subscriber == subscriber) {
subscription.active = false;
subscriptions.remove(i);
i--;
size--;
}
}
}
}
unregister
逻辑比较简单,只是清除subscriptionsByEventType
和typesBySubscriber
集合中保存的数据,防止内存泄漏;
优先级和粘性事件实现
我们直接看下subscribe
方法:
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
...
//1.Priority优先级处理部分
//保存Subscription到subscriptions集合中时,会根据priority进行排序,priority高的排在前面,
//从上面post的时候我们看到最终会顺序遍历subscriptions集合,由此实现发送优先级!!!
int size = subscriptions.size();
for (int i = 0; i <= size; i++) {
if (i == size || subscriberMethod.priority > subscriptions.get(i).subscriberMethod.priority) {
subscriptions.add(i, newSubscription);
break;
}
}
List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);
if (subscribedEvents == null) {
subscribedEvents = new ArrayList<>();
typesBySubscriber.put(subscriber, subscribedEvents);
}
subscribedEvents.add(eventType);
//2.粘性处理部分
// stickyEvents为ConcurrentHashMap集合,key对应post方法参数的clazz,value为post方法参数对象,在调用postSticky的时候,保存到stickyEvents集合中;
//这里判断是sticky方法,则在register的时候就调用postToSubscription方法进行执行了,因此实现了粘性事件,对于后注册先发送的事件也可以接受到!!
if (subscriberMethod.sticky) {
....
Object stickyEvent = stickyEvents.get(eventType);
checkPostStickyEventToSubscription(newSubscription, stickyEvent);
}
}
private void checkPostStickyEventToSubscription(Subscription newSubscription, Object stickyEvent) {
if (stickyEvent != null) {
postToSubscription(newSubscription, stickyEvent, isMainThread());
}
}
EventBus中的设计模式
享元设计模式:
FindState数据获取;
private FindState prepareFindState() {
synchronized (FIND_STATE_POOL) {
for (int i = 0; i < POOL_SIZE; i++) {
FindState state = FIND_STATE_POOL[i];
if (state != null) {
FIND_STATE_POOL[i] = null;
return state;
}
}
}
return new FindState();
}
建造者设计模式:
EventBus支持Builder模式建造;
EventBus(EventBusBuilder builder) {
logger = builder.getLogger();
subscriptionsByEventType = new HashMap<>();
typesBySubscriber = new HashMap<>();
stickyEvents = new ConcurrentHashMap<>();
mainThreadSupport = builder.getMainThreadSupport();
mainThreadPoster = mainThreadSupport != null ? mainThreadSupport.createPoster(this) : null;
backgroundPoster = new BackgroundPoster(this);
asyncPoster = new AsyncPoster(this);
indexCount = builder.subscriberInfoIndexes != null ? builder.subscriberInfoIndexes.size() : 0;
subscriberMethodFinder = new SubscriberMethodFinder(builder.subscriberInfoIndexes,
builder.strictMethodVerification, builder.ignoreGeneratedIndex);
logSubscriberExceptions = builder.logSubscriberExceptions;
logNoSubscriberMessages = builder.logNoSubscriberMessages;
sendSubscriberExceptionEvent = builder.sendSubscriberExceptionEvent;
sendNoSubscriberEvent = builder.sendNoSubscriberEvent;
throwSubscriberException = builder.throwSubscriberException;
eventInheritance = builder.eventInheritance;
executorService = builder.executorService;
}
单例设计模式:
EventBus对象;
public static EventBus getDefault() {
EventBus instance = defaultInstance;
if (instance == null) {
synchronized (EventBus.class) {
instance = EventBus.defaultInstance;
if (instance == null) {
instance = EventBus.defaultInstance = new EventBus();
}
}
}
return instance;
}
总结
看到EventBus
的源码,整体代码架构还是比较清晰,阅读起来也比较轻松,其中一些设计思路也比较常见,如设计模式的运用、缓存机制等等,自己也可以跟着源码简单手写一个属于自己的EventBus
!
结语
如果以上文章对您有一点点帮助,希望您不要吝啬的点个赞加个关注,您每一次小小的举动都是我坚持写作的不懈动力!ღ( ´・ᴗ・` )