EventBus3 源码解读
Posted maplejaw_
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了EventBus3 源码解读相关的知识,希望对你有一定的参考价值。
基本概念
EventBus是一款针对android优化的发布/订阅事件总线库。简便了Activities, Fragments, 以及background threads之间的通信,使发送者与订阅者之间有效解耦。
基本使用
EventBus的使用也极其简单,只需三步即可。
定义一个事件类型。
public class MessageEvent { public final String message; public MessageEvent(String message) { this.message = message; } }
准备订阅者
只需给一个public方法添加@Subscribe注解,那么当发布事件时,订阅者就能匹配并接受处理事件。// This method will be called when a MessageEvent is posted @Subscribe public void onMessageEvent(MessageEvent event){ Toast.makeText(getActivity(), event.message, Toast.LENGTH_SHORT).show(); } // This method will be called when a SomeOtherEvent is posted @Subscribe public void handleSomethingElse(SomeOtherEvent event){ doSomethingWith(event); }
所有的订阅者都应该在事件总线中被注册。只有被注册的订阅者才能收到事件。
@Override public void onStart() { super.onStart(); EventBus.getDefault().register(this); } @Override public void onStop() { EventBus.getDefault().unregister(this); super.onStop(); }
发布事件
你可以在代码的任何地方发布事件,所有更当前事件类型匹配的订阅者都可以接收到这个事件。EventBus.getDefault().post(new MessageEvent("Hello everyone!"));
EventBus是一个非常小巧的库,但是功能却足够强大,接下来去源码里看看。
源码解读
我们从EventBus.getDefault().register(this);
这一行开始,看看getDefault()
做了什么?
public static EventBus getDefault() {
if (defaultInstance == null) {
synchronized (EventBus.class) {
if (defaultInstance == null) {
defaultInstance = new EventBus();
}
}
}
return defaultInstance;
}
可以看出,保持了一个单例。EventBus的构造方法如下。
//=================这两个集合很重要,后面经常出现 START========================
//key为事件类型,value为订阅关系列表。用于查询订阅了该事件的所有订阅关系列表,下称事件类型集合
private final Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType;
//key为订阅者,value为订阅者中的事件类型列表。用于查询该订阅者订阅了的事件。下称订阅者集合
private final Map<Object, List<Class<?>>> typesBySubscriber;
//=======================这两个集合很重要,后面经常出现 END==================
//粘性事件,只保留最近一次的事件(相同事件类型只保留一次)
private final Map<Class<?>, Object> stickyEvents;
//存放SubscriberInfo索引
private List<SubscriberInfoIndex> subscriberInfoIndexes;
//事件类型缓存,key为事件类型,value为当前事件类型继承的所有事件类型
private static final Map<Class<?>, List<Class<?>>> eventTypesCache = new HashMap<>();
//主线程发布者
private final HandlerPoster mainThreadPoster;
//子线程发布者(串行)
private final BackgroundPoster backgroundPoster;
//子线程发布者(另开一个线程)
private final AsyncPoster asyncPoster;
//订阅方法查找器
private final SubscriberMethodFinder subscriberMethodFinder;
//线程池,用于在子线程中发布事件
private final ExecutorService executorService;
private final boolean throwSubscriberException;
private final boolean logSubscriberExceptions;
private final boolean logNoSubscriberMessages;
private final boolean sendSubscriberExceptionEvent;
private final boolean sendNoSubscriberEvent;
private final boolean eventInheritance;
private final int indexCount;
public EventBus() {
this(DEFAULT_BUILDER);
}
//构造方法
EventBus(EventBusBuilder builder) {
//初始化事件类型集合
subscriptionsByEventType = new HashMap<>();
//初始化订阅者集合
typesBySubscriber = new HashMap<>();
//粘性事件集合
stickyEvents = new ConcurrentHashMap<>();
//主线程发布者
mainThreadPoster = new HandlerPoster(this, Looper.getMainLooper(), 10);
//子线程发布者(串行,保持只有一个线程)
backgroundPoster = new BackgroundPoster(this);
//子线程发布者(并行,新起一个线程)
asyncPoster = new AsyncPoster(this);
//以下通过EventBusBuilder进行赋值
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;
}
代码有点长,看的可能有点晕,从源码可以看出最终构造方法中会传入EventBusBuilder对象进行赋值初始化,EventBusBuilder用来配置信息。构造方法主要就是初始化环境。
注册事件
我们现在就来看看register
中的源码。
public void register(Object subscriber) {
//获取Class对象
Class<?> subscriberClass = subscriber.getClass();
//通过方法查找器寻找该订阅者中的订阅方法。
List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
synchronized (this) {
for (SubscriberMethod subscriberMethod : subscriberMethods) {
//加入到集合中保存
subscribe(subscriber, subscriberMethod);
}
}
}
代码很简练,思路也比较清晰。首先获取订阅者的Class对象,然后通过订阅者方法查找器(SubscriberMethodFinder)查询该订阅者中的订阅方法并返回,最后通过subscribe
存入到相关集合中。
在介绍SubscriberMethodFinder之前我们先来了解一下其他几个类。
Subscribe注解
Subscribe用来给订阅方法进行注解,可以指定线程模型,优先级,是否粘性等等。
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface Subscribe {
ThreadMode threadMode() default ThreadMode.POSTING;
boolean sticky() default false;
int priority() default 0;
}
ThreadMode(线程模型)
ThreadMode是个枚举类,可以指定四种线程模型。
public enum ThreadMode {
//表示在哪个线程发布事件就在哪个线程接收事件
POSTING,
//表示在主线程接收事件
MAIN,
//表示在子线程接收事件
BACKGROUND,
//表示开启一个线程接收事件
ASYNC
}
SubscriberMethod(订阅者方法)
通过类名就可以猜出这个类肯定是用来包装订阅方法的,里面存放了方法、线程模型、事件类型(订阅方法中那个参数类型),优先级、是否粘性等。
public class SubscriberMethod {
final Method method;//订阅方法
final ThreadMode threadMode;//线程模型
final Class<?> eventType;//事件类型(就是订阅方法的参数类型)
final int priority;//优先级
final boolean sticky;//是否粘性
public SubscriberMethod(Method method, Class<?> eventType, ThreadMode threadMode, int priority, boolean sticky) {
this.method = method;
this.threadMode = threadMode;
this.eventType = eventType;
this.priority = priority;
this.sticky = sticky;
}
//..
//省略部分源码
}
FindState
FindState是一个临时存储订阅方法的类,在查找完毕后就会被回收。
static class FindState {
//存储订阅方法的集合
final List<SubscriberMethod> subscriberMethods = new ArrayList<>();
//根据事件类型存储订阅方法,用来判断是不是该事件已经被添加过了
final Map<Class, Object> anyMethodByEventType = new HashMap<>();
//根据方法名生成的key存储订阅者的类
final Map<String, Class> subscriberClassByMethodKey = new HashMap<>();
//方法key生成器
final StringBuilder methodKeyBuilder = new StringBuilder(128);
Class<?> subscriberClass;//订阅者的父类
Class<?> clazz;//当前订阅者
boolean skipSuperClasses;//是否跳过父类
SubscriberInfo subscriberInfo;//这个用于注解生成器
//初始化FindState
void initForSubscriber(Class<?> subscriberClass) {
this.subscriberClass = clazz = subscriberClass;
skipSuperClasses = false;
subscriberInfo = null;
}
//回收FindState
void recycle() {
subscriberMethods.clear();
anyMethodByEventType.clear();
subscriberClassByMethodKey.clear();
methodKeyBuilder.setLength(0);
subscriberClass = null;
clazz = null;
skipSuperClasses = false;
subscriberInfo = null;
}
//..
//省略了部分源码
}
Subscription
Subscription表示订阅关系,由订阅者和订阅者方法构成。
final class Subscription {
final Object subscriber;//订阅者
final SubscriberMethod subscriberMethod;//订阅者方法
volatile boolean active;
Subscription(Object subscriber, SubscriberMethod subscriberMethod) {
this.subscriber = subscriber;
this.subscriberMethod = subscriberMethod;
active = true;
}
//..
//省略了部分源码
}
注册事件
现在我们回过头来看看SubscriberMethodFinder的findSubscriberMethods
方法。
List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
//看看集合中有没有缓存
List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);
if (subscriberMethods != null) {
return subscriberMethods;
}
//是否忽略注解器生成的Index类
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;
}
}
一般如果不引用注解生成器,就会直接走反射查找这个路线。
private List<SubscriberMethod> findUsingReflection(Class<?> subscriberClass) {
//获取一个临时保存订阅信息的FindState类
FindState findState = prepareFindState();
//初始化基本信息(其实就是把subscriberClass赋值给findState.clazz)
findState.initForSubscriber(subscriberClass);
while (findState.clazz != null) {
//查找订阅方法
findUsingReflectionInSingleClass(findState);
//定位到父类(就是把父类赋值给findState.clazz,默认跳过系统类)
findState.moveToSuperclass();
}
return getMethodsAndRelease(findState);//从FindState类中取出方法集合,然后释放资源。
}
默认会保持4个FindState循环利用,prepareFindState就是取出一个FindState。然后通过findUsingReflectionInSingleClass
将订阅方法集合暂时保存在FindState中。
private void findUsingReflectionInSingleClass(FindState findState) {
Method[] methods;
try {
//反射获取方法
methods = findState.clazz.getDeclaredMethods();
} catch (Throwable th) {
methods = findState.clazz.getMethods();
findState.skipSuperClasses = true;
}
//循环遍历所有的方法
for (Method method : methods) {
int modifiers = method.getModifiers();//获取修饰符
if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) {//必须为public
Class<?>[] parameterTypes = method.getParameterTypes();获取方法的参数类型。
if (parameterTypes.length == 1) {//只能包含一个参数
//获取Subscribe注解
Subscribe subscribeAnnotation = method.getAnnotation(Subscribe.class);
if (subscribeAnnotation != null) {
Class<?> eventType = parameterTypes[0];
//判断是否没有添加过
if (findState.checkAdd(method, eventType)) {
//获取线程模型等信息
ThreadMode threadMode = subscribeAnnotation.threadMode();
//添加到FindState中的subscriberMethods集合类
findState.subscriberMethods.add(new SubscriberMethod(method, eventType, threadMode,
subscribeAnnotation.priority(), subscribeAnnotation.sticky()));
}
}
}
//...
//省略了else中的代码
}
}
findUsingReflectionInSingleClass
方法主要用于遍历匹配方法,如果满足条件就添加到FindState中的subscriberMethods集合进行保存。既然订阅方法已经遍历完了,那么现在我们回到register
方法中。
可以看出会对每个方法进行遍历然后执行subscribe
。
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
//获取事件类型(就是方法里的那个参数类型)
Class<?> eventType = subscriberMethod.eventType;
//用Subscription包装subscriberMethod,可以看出将订阅者与订阅方法给关联了起来。
Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
//看看事件类型集合里是不是存在过之前的事件类型( CopyOnWriteArrayList是线程安全的)
CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
if (subscriptions == null) {//没有当前事件类型的集合
//第一次须初始化列表
subscriptions = new CopyOnWriteArrayList<>();
//subscriptions为空表示之前没有相同的类型,那么现在就塞进去
subscriptionsByEventType.put(eventType, subscriptions);
} else {
//subscriptions不为空说明有相同事件类型的,判断列表里是不是已经包含了,包含就抛出异常
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;
}
}
List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);
//看看之前有没有相同的订阅者
if (subscribedEvents == null) {
//没有就给当前订阅者new个事件列表放进去
subscribedEvents = new ArrayList<>();
typesBySubscriber.put(subscriber, subscribedEvents);
}
//当到该订阅者下的事件列表里
subscribedEvents.add(eventType);
//判断是不是粘性方法
if (subscriberMethod.sticky) {
if (eventInheritance) {//是否可以响应继承?
Set<Map.Entry<Class<?>, Object>> entries = stickyEvents.entrySet();
for (Map.Entry<Class<?>, 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);
}
}
}
代码有点长,但是逻辑并不复杂,可以看出把订阅方法循环添加到了集合中。然后检查有没有粘性方法,如果有就将最近一次的粘性事件发布即可。
解除事件
接下来看解除事件,为什么不先看发布事件?因为注册和解除是互相呼应的,而且比较简单。趁热看,免得之后又被几个集合给搞懵逼了(说的就是我)。
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 {
Log.w(TAG, "Subscriber to unregister was not registered before: " + subscriber.getClass());
}
}
我们知道,注册事件时会将订阅者以及订阅事件保存到集合中,那么解除事件毋容置疑,首先去集合中查询有没有,如果有,把它从事件类型集合中移除,然后从订阅者集合中移除。unsubscribeByEventType
源码如下。
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--;
}
}
}
}
发布事件
发布事件用ThreadLocal保存了PostingThreadState,PostingThreadState是一个保存事件的类。然后通过循环发送单个事件,可以看出发布事件是串行执行的。
/** Posts the given event to the event bus. */
public void post(Object event) {
//PostingThreadState类似于FindState,用于保存要发布的事件,里面有一个事件队列
PostingThreadState postingState = currentPostingThreadState.get();
List<Object> eventQueue = postingState.eventQueue;
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 {
while (!eventQueue.isEmpty()) {//这里有一个循环
postSingleEvent(eventQueue.remove(0), postingState);//一个一个的按顺序发送事件
}
} finally {
postingState.isPosting = false;
postingState.isMainThread = false;
}
}
}
PostingThreadState的源码如下。
final static class PostingThreadState {
final List<Object> eventQueue = new ArrayList<Object>();//事件列表
boolean isPosting;//是否正在发布事件
boolean isMainThread;//是否在主线程
Subscription subscription; //订阅关系
Object event; //事件
boolean canceled;//是否已被取消
}
接下来看看postSingleEvent方法。如果可以响应事件继承就获取当前事件类型的所有父类。然后逐个发布事件。
private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {
Class<?> eventClass = event.getClass();//获取事件类型
boolean subscriptionFound = false;//是否寻找到订阅关系
if (eventInheritance) {//事件继承?
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);
}
} else {
//发送事件
subscriptionFound = postSingleEventForEventType(event, postingState, eventClass);
}
//..
//省略了部分源码
}
可以看出,最终通过postSingleEventForEventType来发布事件。
private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class<?> eventClass) {
CopyOnWriteArrayList<Subscription> subscriptions;//订阅关系列表
synchronized (this) {
subscriptions = subscriptionsByEventType.get(eventClass);//取出订阅关系礼拜
}
if (subscriptions != null && !subscriptions.isEmpty()) {
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;
}
}
return true;
}
return false;
}
postToSubscription中即是根据订阅关系发布事件。根据不同的线程模型使用不同发布者进行发布。
private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {
switch (subscription.subscriberMethod.threadMode) {
case POSTING:
invokeSubscriber(subscription, event);
break;
case MAIN:
if (isMainThread) {
invokeSubscriber(subscription, event);
} else {
mainThreadPoster.enqueue(subscription, event);
}
break;
case BACKGROUND:
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);
}
}
最终通过反射发布事件。我们只来看一下POSTING源码。其他就不赘述了,操作基本大同小异。
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);
}
}
到此为止,整个EventBus工作流程已经梳理完毕。
最后
- 那个注解生成器是什么鬼?
注解生成器,就是在编译的时候根据注解生成特定的类。就跟自己写的源码一样,执行效率比反射要高很多。
我们在分析subscriberMethodFinder.findSubscriberMethods
查找方法时,提到一般只会走反射,所以没有关心通过注解生成器查找的步骤。
//是否忽略注解器生成的Index类
if (ignoreGeneratedIndex) {
//通过反射查找
subscriberMethods = findUsingReflection(subscriberClass);
} else {
//通过注解生成器生成的类查找
subscriberMethods = findUsingInfo(subscriberClass);
}
现在我们来看下findUsingInfo
源码。
private List<SubscriberMethod> findUsingInfo(Class<?> subscriberClass) {
//初始化FindState
FindState findState = prepareFindState();
findState.initForSubscriber(subscriberClass);
while (findState.clazz != null) {
findState.subscriberInfo = getSubscriberInfo(findState);//获取注解器生成的SubscriberInfo
if (findState.subscriberInfo != null) {
//如果找到了SubscriberInfo就获取方法
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();
}
return getMethodsAndRelease(findState);
}
SubscriberInfo信息如下。
public interface SubscriberInfo {
Class<?> getSubscriberClass();//获取父类
SubscriberMethod[] getSubscriberMethods();//获取订阅方法
SubscriberInfo getSuperSubscriberInfo();//获取父类订阅者信息
boolean shouldCheckSuperclass();
}
getSubscriberInfo用来根据订阅者获取SubscriberInfo。
private SubscriberInfo getSubscriberInfo(FindState findState) {
if (findState.subscriberInfo != null && findState.subscriberInfo.getSuperSubscriberInfo() != null) {
SubscriberInfo superclassInfo = findState.subscriberInfo.getSuperSubscriberInfo();
if (findState.clazz == superclassInfo.getSubscriberClass()) {
return superclassInfo;
}
}
//SubscriberInfoIndex中获取SubscriberInfo
if (subscriberInfoIndexes != null) {
for (SubscriberInfoIndex index : subscriberInfoIndexes) {
SubscriberInfo info = index.getSubscriberInfo(findState.clazz);
if (info != null) {
return info;
}
}
}
return null;
}
EventBus中注解生成器生成代码。
private void createInfoIndexFile(String index) {
BufferedWriter writer = null;
try {
JavaFileObject sourceFile = processingEnv.getFiler().createSourceFile(index);
int period = index.lastIndexOf(‘.‘);
String myPackage = period > 0 ? index.substring(0, period) : null;
String clazz = index.substring(period + 1);
writer = new BufferedWriter(sourceFile.openWriter());
if (myPackage != null) {
writer.write("package " + myPackage + ";\n\n");
}
writer.write("import org.greenrobot.eventbus.meta.SimpleSubscriberInfo;\n");
writer.write("import org.greenrobot.eventbus.meta.SubscriberMethodInfo;\n");
writer.write("import org.greenrobot.eventbus.meta.SubscriberInfo;\n");
writer.write("import org.greenrobot.eventbus.meta.SubscriberInfoIndex;\n\n");
writer.write("import org.greenrobot.eventbus.ThreadMode;\n\n");
writer.write("import java.util.HashMap;\n");
writer.write("import java.util.Map;\n\n");
writer.write("/** This class is generated by EventBus, do not edit. */\n");
writer.write("public class " + clazz + " implements SubscriberInfoIndex {\n");
writer.write(" private static final Map<Class<?>, SubscriberInfo> SUBSCRIBER_INDEX;\n\n");
writer.write(" static {\n");
writer.write(" SUBSCRIBER_INDEX = new HashMap<Class<?>, SubscriberInfo>();\n\n");
writeIndexLines(writer, myPackage);
writer.write(" }\n\n");
writer.write(" private static void putIndex(SubscriberInfo info) {\n");
writer.write(" SUBSCRIBER_INDEX.put(info.getSubscriberClass(), info);\n");
writer.write(" }\n\n");
writer.write(" @Override\n");
writer.write(" public SubscriberInfo getSubscriberInfo(Class<?> subscriberClass) {\n");
writer.write(" SubscriberInfo info = SUBSCRIBER_INDEX.get(subscriberClass);\n");
writer.write(" if (info != null) {\n");
writer.write(" return info;\n");
writer.write(" } else {\n");
writer.write(" return null;\n");
writer.write(" }\n");
writer.write(" }\n");
writer.write("}\n");
} catch (IOException e) {
throw new RuntimeException("Could not write source for " + index, e);
} finally {
if (writer != null) {
try {
writer.close();
} catch (IOException e) {
//Silent
}
}
}
}
writeIndexLines写入订阅者相关的订阅方法信息
private void writeIndexLines(BufferedWriter writer, String myPackage) throws IOException {
for (TypeElement subscriberTypeElement : methodsByClass.keySet()) {
if (classesToSkip.contains(subscriberTypeElement)) {
continue;
}
String subscriberClass = getClassString(subscriberTypeElement, myPackage);
if (isVisible(myPackage, subscriberTypeElement)) {
writeLine(writer, 2,
"putIndex(new SimpleSubscriberInfo(" + subscriberClass + ".class,",
"true,", "new SubscriberMethodInfo[] {");
List<ExecutableElement> methods = methodsByClass.get(subscriberTypeElement);
writeCreateSubscriberMethods(writer, methods, "new SubscriberMethodInfo", myPackage);
writer.write(" }));\n\n");
} else {
writer.write(" // Subscriber not visible to index: " + subscriberClass + "\n");
}
}
}
大家只要知道注解生成器是用来干嘛的就行了,关于注解生成器的原理和使用方法,改篇再作深究,有兴趣的可以自行查阅AnnotationProcessor资料。
以上是关于EventBus3 源码解读的主要内容,如果未能解决你的问题,请参考以下文章