EventBus3 源码解读
2016-06-06 13:30
666 查看
基本概念
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资料。
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories