1.EventBus基本使用步骤
(1)Git地址:https://github.com/greenrobot/EventBus
(2)引入:compile 'org.greenrobot:eventbus:3.1.1'
(3)注册:
onCreate/onStart 中
EventBus.getDefault().register(this);
onStop/onDestory中
EventBus.getDefault().unregister(this);
(4)发送事件
EventBus.getDefault().post("我是来自2的信息");
2.源码解读
(1)EventBus.getDefault() 单利设计模式
public static EventBus getDefault() {
if (defaultInstance == null) {
synchronized (EventBus.class) {
if (defaultInstance == null) {
defaultInstance = new EventBus();
}
}
}
return defaultInstance;
}
(2)EventBus.getDefault().register(this);
public void register(Object subscriber) {
//获取被观察者的class对象
Class> subscriberClass = subscriber.getClass();
//根据class对象得到观察者方法集合
List subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
synchronized (this) {
//遍历找到的观察者方法集合并信息遍历订阅
for (SubscriberMethod subscriberMethod : subscriberMethods) {
subscribe(subscriber, subscriberMethod);
}
}
}
List findSubscriberMethods(Class> subscriberClass) {
//先从缓存中寻找改观察者对象class对应的观察者方法集合
List subscriberMethods = METHOD_CACHE.get(subscriberClass);
//如果缓存中存在就直接返回
if (subscriberMethods != null) {
return subscriberMethods;
}
//这个参数取决于是否使用了编译时注解,类似ButterKnife,
//我们一般不会引入eventbus的apt所以这个参数默认为false
if (ignoreGeneratedIndex) {
//使用了apt会走这里
subscriberMethods = findUsingReflection(subscriberClass);
} else {
//一般情况下会到这里
subscriberMethods = findUsingInfo(subscriberClass);
}
if (subscriberMethods.isEmpty()) {
//这里比较奇葩,如果注入了EventBus但是不用的话
//会直接给你抛异常,也就是说注册了则至少要有一个
//subcriber注释修饰的public方法才行
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;
}
}
private List findUsingInfo(Class> subscriberClass) {
//准备一个查找状态对象,这里就是状态的存储封装,
//这里面用了享元设计模式,不用太关注
FindState findState = prepareFindState();
//根据观察者class对象初始化状态对象
findState.initForSubscriber(subscriberClass);
while (findState.clazz != null) {
//这里在没有使用apt时getSubscriberInfo返回的是null,细节自己看吧
findState.subscriberInfo = getSubscriberInfo(findState);
if (findState.subscriberInfo != null) {
SubscriberMethod[] array = findState.subscriberInfo.getSubscriberMethods();
for (SubscriberMethod subscriberMethod : array) {
if (findState.checkAdd(subscriberMethod.method, subscriberMethod.eventType)) {
findState.subscriberMethods.add(subscriberMethod);
}
}
} else {
//进入核心查找方法
findUsingReflectionInSingleClass(findState);
}
findState.moveToSuperclass();
}
//返回找到并封装好的List,然后释放findState
//这个方法里面会进行享元存储
return getMethodsAndRelease(findState);
}
/**
* 通过反射查找观察者方法集合,放入查找状态存储对象中
*/
private void findUsingReflectionInSingleClass(FindState findState) {
Method[] methods;
try {
// This is faster than getMethods, especially when subscribers are fat classes like Activities
//获取观察者对象的所有方法
//这里补充一点
//getDeclaredMethods()得到该类所有方法,
//包括私有以及接口实现的方法,但是不包括继承的
//getMethods()得到所有public方法,包括接口实现及父类的
//所以作者在这里说用getDeclaredMethods()比用getMethods()要快,
//特别是Activities对象时
methods = findState.clazz.getDeclaredMethods();
} catch (Throwable th) {
// Workaround for java.lang.NoClassDefFoundError, see https://github.com/greenrobot/EventBus/issues/149
//出问题了,获取缓存的并跳过父类
methods = findState.clazz.getMethods();
findState.skipSuperClasses = true;
}
//遍历得到的所有方法
for (Method method : methods) {
//得到方法属性
int modifiers = method.getModifiers();
//判断是否为PUBLIC,
//MODIFIERS_IGNORE 包含(抽象,静态,桥接,合成,后2者是编译器添加的)
//这个if翻译过来就是这个方法必须是公共的,且不能是静态的和抽象的
if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) {
Class>[] parameterTypes = method.getParameterTypes();
//参数数量必须为1,否则也会抛异常
if (parameterTypes.length == 1) {
//获取方法上的Subscribe注解对象
Subscribe subscribeAnnotation = method.getAnnotation(Subscribe.class);
if (subscribeAnnotation != null) {
//获取参数class
Class> eventType = parameterTypes[0];
//这里确保的是不重复添加同意事件类型
if (findState.checkAdd(method, eventType)) {
ThreadMode threadMode = subscribeAnnotation.threadMode();
//将注解中的threadMode,priority,sticky
//和method,eventType对象封装成SubscriberMethod对象
//这里整个观察者的方法就找好了。
findState.subscriberMethods.add(new SubscriberMethod(method, eventType, threadMode,
subscribeAnnotation.priority(), subscribeAnnotation.sticky()));
}
}
} else if (strictMethodVerification && method.isAnnotationPresent(Subscribe.class)) {
String methodName = method.getDeclaringClass().getName() + "." + method.getName();
throw new EventBusException("@Subscribe method " + methodName +
"must have exactly 1 parameter but has " + parameterTypes.length);
}
} else if (strictMethodVerification && method.isAnnotationPresent(Subscribe.class)) {
String methodName = method.getDeclaringClass().getName() + "." + method.getName();
throw new EventBusException(methodName +
" is a illegal @Subscribe method: must be public, non-static, and non-abstract");
}
}
}
// Must be called in synchronized block
/**
* 订阅
* 解析所有的SubscriberMethod,最终放到
* private final Map,CopyOnWriteArrayList> subscriptionsByEventType;
*/
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
//时间类型的class对象,例如post("aaaa"),对应的eventType为String.class
Class> eventType = subscriberMethod.eventType;
//封装成Subscription
Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
//从subscriptionsByEventType获取eventType对应的Subscription
CopyOnWriteArrayList subscriptions = subscriptionsByEventType.get(eventType);
if (subscriptions == null) {
//如果不存在新建后put
subscriptions = new CopyOnWriteArrayList<>();
subscriptionsByEventType.put(eventType, subscriptions);
} else {
//如果存在,且包含则跑出不能重复添加的异常
if (subscriptions.contains(newSubscription)) {
throw new EventBusException("Subscriber " + subscriber.getClass() + " already registered to event "
+ eventType);
}
}
//按照优先级进行将newSubscription添加到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;
}
}
//typesBySubscriber 存储的是观察者对象和事件类型的接口的map
//key 观察者 例如MainActivity对象
//value post时的事件类型 如String.class
List> subscribedEvents = typesBySubscriber.get(subscriber);
if (subscribedEvents == null) {
subscribedEvents = new ArrayList<>();
typesBySubscriber.put(subscriber, subscribedEvents);
}
subscribedEvents.add(eventType);
//处理粘性事件。。。没看懂
if (subscriberMethod.sticky) {
if (eventInheritance) {
// Existing sticky events of all subclasses of eventType have to be considered.
// Note: Iterating over all events may be inefficient with lots of sticky events,
// thus data structure should be changed to allow a more efficient lookup
// (e.g. an additional map storing sub classes of super classes: Class -> List).
Set, Object>> entries = stickyEvents.entrySet();
for (Map.Entry, Object> entry : entries) {
Class> candidateEventType = entry.getKey();
if (eventType.isAssignableFrom(candidateEventType)) {
Object stickyEvent = entry.getValue();
checkPostStickyEventToSubscription(newSubscription, stickyEvent);
}
}
} else {
Object stickyEvent = stickyEvents.get(eventType);
checkPostStickyEventToSubscription(newSubscription, stickyEvent);
}
}
}
//注册工作到此全部完成
(3)EventBus.getDefault().post("")
public void post(Object event) {
//一个线程一个PostingThreadState对象
PostingThreadState postingState = currentPostingThreadState.get();
//添加到时间队列
List
/**
* 这里绕来绕去最终会走postSingleEventForEventType
* 然后再调用postToSubscription方法
*/
private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {
//获取事件类型
Class> eventClass = event.getClass();
boolean subscriptionFound = false;
if (eventInheritance) {
List> eventTypes = lookupAllEventTypes(eventClass);
int countTypes = eventTypes.size();
for (int h = 0; h < countTypes; h++) {
Class> clazz = eventTypes.get(h);
subscriptionFound |= postSingleEventForEventType(event, postingState, clazz);
}
} else {
subscriptionFound = postSingleEventForEventType(event, postingState, eventClass);
}
if (!subscriptionFound) {
if (logNoSubscriberMessages) {
logger.log(Level.FINE, "No subscribers registered for event " + eventClass);
}
if (sendNoSubscriberEvent && eventClass != NoSubscriberEvent.class &&
eventClass != SubscriberExceptionEvent.class) {
post(new NoSubscriberEvent(this, event));
}
}
}
/**
* 核心发布方法
*/
private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {
switch (subscription.subscriberMethod.threadMode) {
case POSTING://需要的是相同的的现成
//直接执行
invokeSubscriber(subscription, event);
break;
case MAIN:
if (isMainThread) {
//post时在主线程直接执行
invokeSubscriber(subscription, event);
} else {
//需要在主线程,但是发送时不在主线程,通过handle回到主线程执行
mainThreadPoster.enqueue(subscription, event);
}
break;
case MAIN_ORDERED:
//需要主线程按顺序
if (mainThreadPoster != null) {
mainThreadPoster.enqueue(subscription, event);
} else {
// temporary: technically not correct as poster not decoupled from subscriber
//与post同线程
invokeSubscriber(subscription, event);
}
break;
case BACKGROUND:
//需要子线程
if (isMainThread) {
//post时在主线程则需要backgroundPoster切回子线程
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);
}
}
/**
*反射调用方法
*/
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);
}
}
(4) EventBus.getDefault().unregister(this);
移除仿泄露
public synchronized void unregister(Object subscriber) {
List> subscribedTypes = typesBySubscriber.get(subscriber);
if (subscribedTypes != null) {
for (Class> eventType : subscribedTypes) {
//移除观察者的事件信息
unsubscribeByEventType(subscriber, eventType);
}
//移除观察者
typesBySubscriber.remove(subscriber);
} else {
logger.log(Level.WARNING, "Subscriber to unregister was not registered before: " + subscriber.getClass());
}
}
3 总结
本质就是一个单利,维护两个集合
一个:Map
一个: Map