EventBus源码解析
注册
我们平时使用eventbus要先注册,这里看一下注册的逻辑
EventBus.getDefault().register(this)
//这里我们可以看到这个EventBus是一个单例
public static EventBus getDefault() {
if (defaultInstance == null) {
synchronized (EventBus.class) {
if (defaultInstance == null) {
defaultInstance = new EventBus();
}
}
}
return defaultInstance;
}
接下来我们看一下注册eventbus的代码
public void register(Object subscriber) {
Class<?> subscriberClass = subscriber.getClass();//首先我们获取订阅者的Class
List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);//这里通过subscriberMethodFinder来找到所有的订阅方法
synchronized (this) {
for (SubscriberMethod subscriberMethod : subscriberMethods) {
subscribe(subscriber, subscriberMethod);//依次订阅
}
}
}
然后我们看一下订阅方法是如何实现的
// Must be called in synchronized block 由注释可知,这个必须是被同步调用
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {//两个参数,一个是订阅者,一个是从订阅者中分离出来的订阅方法
Class<?> eventType = subscriberMethod.eventType;//这有一个eventType 到底是啥呢,我们猜测是我们订阅时自己创建的event类,也就是订阅方法的参数
Subscription newSubscription = new Subscription(subscriber, subscriberMethod);//生成一个订阅 要分清这些东西都是eventbus自己的类,和rxjava可没啥关系
CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType);//根据我们订阅的事件类型获取缓存的订阅 这个subscriptionsByEventType就是一个hashmap
if (subscriptions == null) {//之前没有对此类事件订阅
subscriptions = new CopyOnWriteArrayList<>();//生成对这个事件的订阅list
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;
}
}
List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);//这个typesBySubscriber也是一个map,持有订阅者所订阅的event的Class
if (subscribedEvents == null) {//之前没有的话,新建
subscribedEvents = new ArrayList<>();
typesBySubscriber.put(subscriber, subscribedEvents);
}
subscribedEvents.add(eventType);//把eventtype加进去
if (subscriberMethod.sticky) {//这个属性 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);
}
}
}
取消注册
这里我们接着看一下取消注册的逻辑
EventBus.getDefault().unregister(this)
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);//从map中删除这个订阅者
} else {
Log.w(TAG, "Subscriber to unregister was not registered before: " + subscriber.getClass());
}
}
private void unsubscribeByEventType(Object subscriber, Class<?> eventType) {
List<Subscription> subscriptions = subscriptionsByEventType.get(eventType);//查找所有订阅了eventtype的订阅关系
if (subscriptions != null) {
int size = subscriptions.size();
for (int i = 0; i < size; i++) {
Subscription subscription = subscriptions.get(i);
if (subscription.subscriber == subscriber) {//停止并移除由subscriber产生的订阅关系
subscription.active = false;
subscriptions.remove(i);
i--;
size--;
}
}
}
}
我们可以看到取消注册逻辑并不复杂,分别在两个map中移除相应的关系就可以了
分发事件
先看看简单的分发事件
public void post(Object event) {
PostingThreadState postingState = currentPostingThreadState.get();//currentPostingThreadState是一个threadlocal,保存PostingThreadState
//我们在这里取出当前线程的PostingThreadState
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
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();//拿到事件的class
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);//发送事件
}
if (!subscriptionFound) {//没找到
if (logNoSubscriberMessages) {
Log.d(TAG, "No subscribers registered for event " + eventClass);
}
if (sendNoSubscriberEvent && eventClass != NoSubscriberEvent.class &&
eventClass != SubscriberExceptionEvent.class) {
post(new NoSubscriberEvent(this, event));//发送没有订阅者的事件
}
}
}
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);
}
}
接下来我们依次进行分析
invokeSubscriber
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);
}
}
然后我们看到当需要在非本线程调用的时候,采用的是***Poster.enqueue的方式,我们来看一下这是个啥
Poster
在分发事件的时候,我们用到了mainThreadPoster,backgroundPoster 和 asyncPoster,但其实点进去看看实现,根本就没有Poster这么个类或者接口,是我胡咧咧的,只是他们名字长得比较像,在这里的用途也差不多哈哈哈
这三个都是Eventbus实例持有的对象
private final HandlerPoster mainThreadPoster;
private final BackgroundPoster backgroundPoster;
private final AsyncPoster asyncPoster;
//在Eventbus构造方法里面实例化
mainThreadPoster = new HandlerPoster(this, Looper.getMainLooper(), 10);//传入主线程Looper
backgroundPoster = new BackgroundPoster(this);
asyncPoster = new AsyncPoster(this);
我们分别看一下这三个'Poster'的实现
HandlerPoster
看名字猜得出,和handler有关 上源码
final class HandlerPoster extends Handler {
private final PendingPostQueue queue;
private final int maxMillisInsideHandleMessage;
private final EventBus eventBus;
private boolean handlerActive;
HandlerPoster(EventBus eventBus, Looper looper, int maxMillisInsideHandleMessage) {
super(looper);
this.eventBus = eventBus;
this.maxMillisInsideHandleMessage = maxMillisInsideHandleMessage;
queue = new PendingPostQueue();//构造方法实例化一个队列,用于存储等待发送事件
}
void enqueue(Subscription subscription, Object event) {//这就是我们把事件发送给订阅者了
PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);//包装成一个等待的发送
synchronized (this) {//存加锁
queue.enqueue(pendingPost);//把这个等待入队
if (!handlerActive) {//这个handler是否正在运行
handlerActive = true;//设置正在运行
if (!sendMessage(obtainMessage())) {//发送一个消息 这个消息随便,反正这个handler就这里发送消息
throw new EventBusException("Could not send handler message");
}
}
}
}
@Override
public void handleMessage(Message msg) {//looper所在线程收到并处理消息
boolean rescheduled = false;//是否推迟
try {
long started = SystemClock.uptimeMillis();//开始事件
while (true) {//循环
PendingPost pendingPost = queue.poll();//从等待发送事件队列中取出一个
if (pendingPost == null) {//没了,防止存的数据还没存好取不出来,加锁等存好了再取一遍
synchronized (this) {
// Check again, this time in synchronized
pendingPost = queue.poll();
if (pendingPost == null) {//彻底没数据了,停止活动,return
handlerActive = false;
return;
}
}
}
eventBus.invokeSubscriber(pendingPost);//在lopper所在线程调用订阅者的方法
long timeInMethod = SystemClock.uptimeMillis() - started;//方法运行事件
if (timeInMethod >= maxMillisInsideHandleMessage) {//如果订阅者方法运行的事件超时了
if (!sendMessage(obtainMessage())) {//重启一下这个队列 置于原因,现在不知道
throw new EventBusException("Could not send handler message");
}
rescheduled = true;
return;
}
}
} finally {
handlerActive = rescheduled;
}
}
}
BackgroundPoster
后台运行 直接上代码
final class BackgroundPoster implements Runnable {//这就是一个runnable
private final PendingPostQueue queue;
private final EventBus eventBus;
private volatile boolean executorRunning;
BackgroundPoster(EventBus eventBus) {
this.eventBus = eventBus;
queue = new PendingPostQueue();
}
public void enqueue(Subscription subscription, Object event) {//入队操作
PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);//包装成PendingPost
synchronized (this) {
queue.enqueue(pendingPost);//入队
if (!executorRunning) {//执行器是否正在执行
executorRunning = true;//执行
eventBus.getExecutorService().execute(this);//这里看到,我们用eventBus持有的线程池来执行此runnable
}
}
}
@Override
public void run() {//runnable方法, 和上面的handlerPoster差不多,有两处不同
try {
try {
while (true) {
PendingPost pendingPost = queue.poll(1000);//1这里传参1000 暂时不知道是啥
if (pendingPost == null) {
synchronized (this) {
// Check again, this time in synchronized
pendingPost = queue.poll();
if (pendingPost == null) {
executorRunning = false;
return;
}
}
}
//没有限制最大事件,也不知道是啥
eventBus.invokeSubscriber(pendingPost);
}
} catch (InterruptedException e) {
Log.w("Event", Thread.currentThread().getName() + " was interruppted", e);
}
} finally {
executorRunning = false;
}
}
}
AsyncPoster
异步poster
class AsyncPoster implements Runnable {
private final PendingPostQueue queue;
private final EventBus eventBus;
AsyncPoster(EventBus eventBus) {
this.eventBus = eventBus;
queue = new PendingPostQueue();
}
public void enqueue(Subscription subscription, Object event) {
PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);//这里可以看出来,所谓异步就是每一次订阅事件的发送都直接丢给线程池去处理
queue.enqueue(pendingPost);
eventBus.getExecutorService().execute(this);
}
@Override
public void run() {
PendingPost pendingPost = queue.poll();
if(pendingPost == null) {
throw new IllegalStateException("No pending post available");
}
eventBus.invokeSubscriber(pendingPost);
}
}
好啦,截止到这里,一个比较简单的eventbus注册订阅发送事件接受事件取消注册的流程就走完了
但是前面的代码里有几个方法和类我们并没有详细的看,只是猜了猜他们是干啥的,下面先详细的看一下
按照顺序,第一个类就是SubscriberMethod了,它是在注册的时候由subscriberMethodFinder.findSubscriberMethods(subscriberClass)生成的并保存的,那我们一起看一下
SubscriberMethod
SubscriberMethod类
public class SubscriberMethod {
final Method method;//订阅者的方法
final ThreadMode threadMode;//回调模式,上面讲过了
final Class<?> eventType;//订阅的事件类型
final int priority;//优先级
final boolean sticky;//是否是黏性
/** Used for efficient comparison */
String methodString;
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;
}
@Override
public boolean equals(Object other) {//重写equals方法
if (other == this) {
return true;
} else if (other instanceof SubscriberMethod) {
checkMethodString();//这个实际上就是使用类名+方法名+eventype类型拼接,也就是说判断这三个是否一样
SubscriberMethod otherSubscriberMethod = (SubscriberMethod)other;
otherSubscriberMethod.checkMethodString();
// Don't use method.equals because of http://code.google.com/p/android/issues/detail?id=7811#c6
return methodString.equals(otherSubscriberMethod.methodString);
} else {
return false;
}
}
//使用类名+方法名+eventype类型拼接 并缓存
private synchronized void checkMethodString() {
if (methodString == null) {
// Method.toString has more overhead, just take relevant parts of the method
StringBuilder builder = new StringBuilder(64);
builder.append(method.getDeclaringClass().getName());
builder.append('#').append(method.getName());
builder.append('(').append(eventType.getName());
methodString = builder.toString();
}
}
@Override
public int hashCode() {
return method.hashCode();
}
}
接下来我们看看一个SubscriberMethod是怎么生成的
SubscriberMethodFinder
这个类相对来说比较重要啦,我们来看一下源码,比较多
class SubscriberMethodFinder {
/*
* In newer class files, compilers may add methods. Those are called bridge or synthetic methods.
* EventBus must ignore both. There modifiers are not public but defined in the Java class file format:
* http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.6-200-A.1
*/
private static final int BRIDGE = 0x40;
private static final int SYNTHETIC = 0x1000;
private static final int MODIFIERS_IGNORE = Modifier.ABSTRACT | Modifier.STATIC | BRIDGE | SYNTHETIC;//要忽略的方法修饰符
private static final Map<Class<?>, List<SubscriberMethod>> METHOD_CACHE = new ConcurrentHashMap<>();//方法缓存hashmap
private List<SubscriberInfoIndex> subscriberInfoIndexes;
private final boolean strictMethodVerification;
private final boolean ignoreGeneratedIndex;
private static final int POOL_SIZE = 4;
private static final FindState[] FIND_STATE_POOL = new FindState[POOL_SIZE];//是一个findstate的空闲池
//上面就是参数了,有好多我们都不认识,没关系,一步一步看
SubscriberMethodFinder(List<SubscriberInfoIndex> subscriberInfoIndexes, boolean strictMethodVerification,
boolean ignoreGeneratedIndex) {//这是构造方法
this.subscriberInfoIndexes = subscriberInfoIndexes;//这个我们使用注解处理器生成的,,里面存贮了所有添加了sub注解的可用的方法和他的索引
this.strictMethodVerification = strictMethodVerification;//是否对方法严格检查模式,这样的话不符合的方法会报错
this.ignoreGeneratedIndex = ignoreGeneratedIndex;//是否忽略注解处理器生成的索引
}
List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {//这里就是根据订阅者的Class类生成咱们的SubscriberMethod的方法了
List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);//先看看缓存里面有没有
if (subscriberMethods != null) {//有的话直接返回
return subscriberMethods;
}
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> findUsingInfo(Class<?> subscriberClass) {
FindState findState = prepareFindState();//这里有一个FindState内部类,保存了一次查找的状态 这么说不是很清晰,继续看
//看完了各大概,现在回来看看prepareFindState();
findState.initForSubscriber(subscriberClass);//通过订阅者Class初始化
while (findState.clazz != null) {//循环查找
findState.subscriberInfo = getSubscriberInfo(findState);//查找并设置info给state
if (findState.subscriberInfo != null) {//订阅者信息不为空
SubscriberMethod[] array = findState.subscriberInfo.getSubscriberMethods();//生成所有的SubscriberMethod
for (SubscriberMethod subscriberMethod : array) {
if (findState.checkAdd(subscriberMethod.method, subscriberMethod.eventType)) {//循环比对时都需要添加
findState.subscriberMethods.add(subscriberMethod);
}
}
} else {
findUsingReflectionInSingleClass(findState);//使用反射查找
}
findState.moveToSuperclass();//指针移动到父类
}
return getMethodsAndRelease(findState);
}
private List<SubscriberMethod> getMethodsAndRelease(FindState findState) {//查找完毕,
List<SubscriberMethod> subscriberMethods = new ArrayList<>(findState.subscriberMethods);//取出subscriberMethods
findState.recycle();//回收
synchronized (FIND_STATE_POOL) {//放进回收池
for (int i = 0; i < POOL_SIZE; i++) {
if (FIND_STATE_POOL[i] == null) {
FIND_STATE_POOL[i] = findState;
break;
}
}
}
return subscriberMethods;
}
private FindState prepareFindState() {
synchronized (FIND_STATE_POOL) {//从闲置池中拿一个findstate出来
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();//如果没有就搞一个新的
}
private SubscriberInfo getSubscriberInfo(FindState findState) {
//第一次查找的话状态里肯定没有保存subscriberInfo
if (findState.subscriberInfo != null && findState.subscriberInfo.getSuperSubscriberInfo() != null) {
SubscriberInfo superclassInfo = findState.subscriberInfo.getSuperSubscriberInfo();
if (findState.clazz == superclassInfo.getSubscriberClass()) {
return superclassInfo;
}
}
//设置了索引
if (subscriberInfoIndexes != null) {
for (SubscriberInfoIndex index : subscriberInfoIndexes) {//遍历索引
SubscriberInfo info = index.getSubscriberInfo(findState.clazz);
if (info != null) {
return info;
}
}
}
return null;
}
private List<SubscriberMethod> findUsingReflection(Class<?> subscriberClass) {
FindState findState = prepareFindState();
findState.initForSubscriber(subscriberClass);
while (findState.clazz != null) {
findUsingReflectionInSingleClass(findState);
findState.moveToSuperclass();
}
return getMethodsAndRelease(findState);
}
private void findUsingReflectionInSingleClass(FindState findState) {//使用反射查找
Method[] methods;//方法
try {
// This is faster than getMethods, especially when subscribers are fat classes like 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();//获取修饰符
if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) {//不包含上面的几个修饰符
Class<?>[] parameterTypes = method.getParameterTypes();//获取方法的所有参数
if (parameterTypes.length == 1) {//只有一个参数
Subscribe subscribeAnnotation = method.getAnnotation(Subscribe.class);//是否添加了@Subscribe注解
if (subscribeAnnotation != null) {//添加了
Class<?> eventType = parameterTypes[0];//拿到参数Class
if (findState.checkAdd(method, eventType)) {//检查添加事件类型和对应的方法
ThreadMode threadMode = subscribeAnnotation.threadMode(); //获取注解生成的线程模式
findState.subscriberMethods.add(new SubscriberMethod(method, eventType, threadMode,
subscribeAnnotation.priority(), subscribeAnnotation.sticky()));//添加一个SubscriberMethod进去
}
}
} else if (strictMethodVerification && method.isAnnotationPresent(Subscribe.class)) {//如果添加了Subscribe注解并且开启了对方法的严格检查
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)) {//如果添加了Subscribe注解并且开启了对方法的严格检查
String methodName = method.getDeclaringClass().getName() + "." + method.getName();//报错
throw new EventBusException(methodName +
" is a illegal @Subscribe method: must be public, non-static, and non-abstract");
}
}
}
static void clearCaches() {
METHOD_CACHE.clear();
}
static class FindState { //内部类 代表一个查找的状态
final List<SubscriberMethod> subscriberMethods = new ArrayList<>();//SubscriberMethod数组
final Map<Class, Object> anyMethodByEventType = new HashMap<>();//方法和eventType的对应集合
final Map<String, Class> subscriberClassByMethodKey = new HashMap<>();//订阅者的类和MethodKey的对应集合
final StringBuilder methodKeyBuilder = new StringBuilder(128);//用于构造methodKey
Class<?> subscriberClass;//本订阅者的类
Class<?> clazz;//要被查找的类指针
boolean skipSuperClasses;//是否跳过父类
SubscriberInfo subscriberInfo;//订阅者信息 这是一个接口
//初始化
void initForSubscriber(Class<?> subscriberClass) {//初始化订阅者Class
this.subscriberClass = clazz = subscriberClass;//当前类指向订阅者类
skipSuperClasses = false;//设置默认
subscriberInfo = null;
}
//回收
void recycle() {
subscriberMethods.clear();//清空各个数组
anyMethodByEventType.clear();
subscriberClassByMethodKey.clear();
methodKeyBuilder.setLength(0);
subscriberClass = null;
clazz = null;
skipSuperClasses = false;
subscriberInfo = null;
}
//这个方法的代码,我对于中间的异常抛出不是很理解,在这里请教一下各位老哥,禁止这种情况的意义是啥呢?比如父类有两个方法订阅相同的event,子类重写了这两个方法并也添加了@Sub注解,就会报异常了,但是和重写或者相同的event关系不大,看下面的代码就知道只有子类父类订阅同event以及重写的方法数量特定的情况下才会触发这个异常
boolean checkAdd(Method method, Class<?> eventType) {
// 2 level check: 1st level with event type only (fast), 2nd level with complete signature when required.
//判断两次
// Usually a subscriber doesn't have methods listening to the same event type.//通常一个订阅者不会有多个方法订阅同一个event
Object existing = anyMethodByEventType.put(eventType, method);//之前是否有方法订阅此事件
if (existing == null) {//没有,返回true
return true;
} else {
//之前有方法订阅这个事件了 这就说明在订阅者中出现了多个方法都订阅了此事件
if (existing instanceof Method) {//这里进行判断 如果是method,说明里面的method
if (!checkAddWithMethodSignature((Method) existing, eventType)) {
// Paranoia check//顾明思意,这是一个'妄想'的检查,理论上不会出现这种情况 所以我们先看看看这到底检查的是个啥
throw new IllegalStateException();//报错
}
// Put any non-Method object to "consume" the existing Method
anyMethodByEventType.put(eventType, this);//
}
return checkAddWithMethodSignature(method, eventType);
}
}
66
private boolean checkAddWithMethodSignature(Method method, Class<?> eventType) {//这个方法的作用是把method和eventtype保存起来,如果之前保存过一样说明一个是父类的方法,
//一个是子类的方法,这种情况下 我们选择保留子类的方法
//如果新的是子类或者以前没有保存过,返回true 反之返回false
methodKeyBuilder.setLength(0);
methodKeyBuilder.append(method.getName());
methodKeyBuilder.append('>').append(eventType.getName());
String methodKey = methodKeyBuilder.toString();//methodKey = "methodName>eventTypeName"
Class<?> methodClass = method.getDeclaringClass();//获取声明这个方法的class
Class<?> methodClassOld = subscriberClassByMethodKey.put(methodKey, methodClass);//看看之前有没有保存这种方法名相同参数也相同的方法?
if (methodClassOld == null || methodClassOld.isAssignableFrom(methodClass)) {
//如果没有,说明是不同名的方法,返回true
//或者已有的方法是新方法的父类调用的 返回true
// Only add if not already found in a sub class
return true;
} else {
// Revert the put, old class is further down the class hierarchy
subscriberClassByMethodKey.put(methodKey, methodClassOld);//返回false
return false;
}
}
void moveToSuperclass() {//进去父类继续寻找
if (skipSuperClasses) {//是否跳过父类
clazz = null;
} else {
clazz = clazz.getSuperclass();//clazz为父类
String clazzName = clazz.getName();
/** Skip system classes, this just degrades performance. */
if (clazzName.startsWith("java.") || clazzName.startsWith("javax.") || clazzName.startsWith("android.")) {//父类为系统类,跳过
clazz = null;
}
}
}
}
}
黏性
前面看到这个就表示没见过,现在先把它怼了
因为我没用过TT,所以直接去百度了 有位老哥是这么解释的
所谓的黏性事件,就是指发送了该事件之后再订阅者依然能够接收到的事件。
使用黏性事件的时候有两个地方需要做些修改。一个是订阅事件的地方,
另一个是发布事件的地方,调用EventBus的postSticky方法来发布事件
好,这样理解就比较清晰了,因为黏性事件是先发送,后订阅,那我们看源码也按照这个顺序来
postSticky
public void postSticky(Object event) {
synchronized (stickyEvents) {
stickyEvents.put(event.getClass(), event);
}
// Should be posted after it is putted, in case the subscriber wants to remove immediately
post(event);
}
这一段代码可以说很简单了=,=就是把我们的黏性事件加了入了一个map里面存了起来,这里我们也就知道了,当发送多个类型的黏性事件时,后注册的订阅者只会触发最后一个
下面就可以说一说注册的情况了
注册
上面之前已经上了代码,我们这里就只选和黏性有关的东西
if (subscriberMethod.sticky) {//这里,注册方法的时候判断这是不是粘性的
if (eventInheritance) {//event事件继承是否开启
//暂时省略这部分代码
} else {
Object stickyEvent = stickyEvents.get(eventType);//取出相应的粘性事件
checkPostStickyEventToSubscription(newSubscription, stickyEvent);//检查是否发送这个粘性事件给当前订阅
}
}
private void checkPostStickyEventToSubscription(Subscription newSubscription, Object stickyEvent) {
if (stickyEvent != null) {//event 存在
// 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());//这里直接发送这个黏性事件
}
}
可见这个黏性比较简单,只是在发送的时候存储起来,等待有人注册的时候看看是否需要发送,如果需要就发送
下面我们来看看上面省略的eventInheritance
eventInheritance
这个是干什么的呢?
我从网上搜来一段描述
如果post(A),A extends B implements C,D implements C
那么onEvent(A)、onEvent(B)、onEvent(C)会被调用,onEvent(D)不会被调用
很清晰啊,下面我就上相关代码,看看是如何实现的
if (eventInheritance) {//这里是发送非黏性event的代码块,上面有出现过,只不过我们忽略了这个开启了event继承模式情况下里面的逻辑
List<Class<?>> eventTypes = lookupAllEventTypes(eventClass);//获取这个event的所有父类及接口
int countTypes = eventTypes.size();
for (int h = 0; h < countTypes; h++) {//依次发送
Class<?> clazz = eventTypes.get(h);
subscriptionFound |= postSingleEventForEventType(event, postingState, clazz);//发送事件,只要有一次成功就成功
}
} else {//不开启event继承模式
subscriptionFound = postSingleEventForEventType(event, postingState, eventClass);//发送事件
}
lookupAllEventTypes方法:
/** Looks up all Class objects including super classes and interfaces. Should also work for interfaces. */
private static List<Class<?>> lookupAllEventTypes(Class<?> eventClass) {
synchronized (eventTypesCache) {
List<Class<?>> eventTypes = eventTypesCache.get(eventClass);//这是一个eventClass对应其父类及所有的接口的缓存,第一次查询肯定是空的
if (eventTypes == null) {//没有缓存
eventTypes = new ArrayList<>();
Class<?> clazz = eventClass;//先指向当前clazz
while (clazz != null) {//不为空
eventTypes.add(clazz);//放入list
addInterfaces(eventTypes, clazz.getInterfaces());//把所有的接口也放进去
clazz = clazz.getSuperclass();//指向父类,继续查找添加
}
eventTypesCache.put(eventClass, eventTypes);//加入缓存
}
return eventTypes;//返回
}
}
addInterfaces方法:
/** Recurses through super interfaces. */
static void addInterfaces(List<Class<?>> eventTypes, Class<?>[] interfaces) {
for (Class<?> interfaceClass : interfaces) {
if (!eventTypes.contains(interfaceClass)) {//如果list中不存在
eventTypes.add(interfaceClass);//加入
addInterfaces(eventTypes, interfaceClass.getInterfaces());//递归加入
}
}
}
下面我们再看看黏性事件的情况
if (subscriberMethod.sticky) {//这是订阅者注册的时候
if (eventInheritance) {//开启了event继承接收
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);
}
}
注解处理器
@SupportedAnnotationTypes("org.greenrobot.eventbus.Subscribe")//要处理的注解
@SupportedOptions(value = {"eventBusIndex", "verbose"})//要处理的属性 第一个就是在build中设置的生成的文件名,第二个'冗余模式',是否打印输出信息
public class EventBusAnnotationProcessor extends AbstractProcessor {
public static final String OPTION_EVENT_BUS_INDEX = "eventBusIndex";
public static final String OPTION_VERBOSE = "verbose";
/** Found subscriber methods for a class (without superclasses). */
private final ListMap<TypeElement, ExecutableElement> methodsByClass = new ListMap<>();//一个map 方法和class的对应
//
private final Set<TypeElement> classesToSkip = new HashSet<>();
private boolean writerRoundDone;
private int round;
private boolean verbose;
@Override
public SourceVersion getSupportedSourceVersion() {
return SourceVersion.latest();//支持的最低版本
}
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment env) {
Messager messager = processingEnv.getMessager();//用于打印log的对象
try {
String index = processingEnv.getOptions().get(OPTION_EVENT_BUS_INDEX);//文件名
if (index == null) {
messager.printMessage(Diagnostic.Kind.ERROR, "No option " + OPTION_EVENT_BUS_INDEX +
" passed to annotation processor");
return false;
}
verbose = Boolean.parseBoolean(processingEnv.getOptions().get(OPTION_VERBOSE));//这个暂时不知道是啥
int lastPeriod = index.lastIndexOf('.');//截取文件夹名
String indexPackage = lastPeriod != -1 ? index.substring(0, lastPeriod) : null;
round++;//计数加一
if (verbose) {//打印信息
messager.printMessage(Diagnostic.Kind.NOTE, "Processing round " + round + ", new annotations: " +
!annotations.isEmpty() + ", processingOver: " + env.processingOver());
}
if (env.processingOver()) {//这个暂时不懂是啥 todo
if (!annotations.isEmpty()) {
messager.printMessage(Diagnostic.Kind.ERROR,
"Unexpected processing state: annotations still available after processing over");
return false;
}
}
if (annotations.isEmpty()) {//empty
return false;
}
if (writerRoundDone) {//是否已经写完了
messager.printMessage(Diagnostic.Kind.ERROR,
"Unexpected processing state: annotations still available after writing.");
}
collectSubscribers(annotations, env, messager);//收集Subscribers
checkForSubscribersToSkip(messager, indexPackage);//检查Subscriber应不应该被跳过
if (!methodsByClass.isEmpty()) {//不为空,写入文件
createInfoIndexFile(index);
} else {
messager.printMessage(Diagnostic.Kind.WARNING, "No @Subscribe annotations found");
}
writerRoundDone = true;
} catch (RuntimeException e) {
// IntelliJ does not handle exceptions nicely, so log and print a message
e.printStackTrace();
messager.printMessage(Diagnostic.Kind.ERROR, "Unexpected error in EventBusAnnotationProcessor: " + e);
}
return true;
}
//剩下的方法没有写什么注释了,感兴趣的老哥可以自己看下//
private void collectSubscribers(Set<? extends TypeElement> annotations, RoundEnvironment env, Messager messager) {
for (TypeElement annotation : annotations) {//循环注解
Set<? extends Element> elements = env.getElementsAnnotatedWith(annotation);//获取这个注解对应的元素
for (Element element : elements) {
if (element instanceof ExecutableElement) {//如果是方法
ExecutableElement method = (ExecutableElement) element;
if (checkHasNoErrors(method, messager)) {//检查有没有错误
TypeElement classElement = (TypeElement) method.getEnclosingElement();//获取声明这个方法的类
methodsByClass.putElement(classElement, method);//放进去
}
} else {//不是方法,报错
messager.printMessage(Diagnostic.Kind.ERROR, "@Subscribe is only valid for methods", element);
}
}
}
}
private boolean checkHasNoErrors(ExecutableElement element, Messager messager) {
if (element.getModifiers().contains(Modifier.STATIC)) {//不能是静态方法
messager.printMessage(Diagnostic.Kind.ERROR, "Subscriber method must not be static", element);
return false;
}
if (!element.getModifiers().contains(Modifier.PUBLIC)) {//必须是public方法
messager.printMessage(Diagnostic.Kind.ERROR, "Subscriber method must be public", element);
return false;
}
List<? extends VariableElement> parameters = ((ExecutableElement) element).getParameters();//必须有且只有一个参数
if (parameters.size() != 1) {
messager.printMessage(Diagnostic.Kind.ERROR, "Subscriber method must have exactly 1 parameter", element);
return false;
}
return true;
}
/**
* 如果索引不可见其类或任何涉及的事件类,则应跳过订阅者类。
*/
private void checkForSubscribersToSkip(Messager messager, String myPackage) {
for (TypeElement skipCandidate : methodsByClass.keySet()) {//循环所有的查到的类
TypeElement subscriberClass = skipCandidate;
while (subscriberClass != null) {
if (!isVisible(myPackage, subscriberClass)) {//这个类相对目标包不可见
boolean added = classesToSkip.add(skipCandidate);//添加进去
if (added) {//打印log
String msg;
if (subscriberClass.equals(skipCandidate)) {
msg = "Falling back to reflection because class is not public";
} else {
msg = "Falling back to reflection because " + skipCandidate +
" has a non-public super class";
}
messager.printMessage(Diagnostic.Kind.NOTE, msg, subscriberClass);
}
break;
}
List<ExecutableElement> methods = methodsByClass.get(subscriberClass);//找到所有对应的方法
if (methods != null) {
for (ExecutableElement method : methods) {//循环
String skipReason = null;
VariableElement param = method.getParameters().get(0);//参数对象
TypeMirror typeMirror = getParamTypeMirror(param, messager);//
if (!(typeMirror instanceof DeclaredType) ||
!(((DeclaredType) typeMirror).asElement() instanceof TypeElement)) {
skipReason = "event type cannot be processed";
}
if (skipReason == null) {
TypeElement eventTypeElement = (TypeElement) ((DeclaredType) typeMirror).asElement();
if (!isVisible(myPackage, eventTypeElement)) {
skipReason = "event type is not public";
}
}
if (skipReason != null) {
boolean added = classesToSkip.add(skipCandidate);
if (added) {
String msg = "Falling back to reflection because " + skipReason;
if (!subscriberClass.equals(skipCandidate)) {
msg += " (found in super class for " + skipCandidate + ")";
}
messager.printMessage(Diagnostic.Kind.NOTE, msg, param);
}
break;
}
}
}
subscriberClass = getSuperclass(subscriberClass);
}
}
}
private TypeMirror getParamTypeMirror(VariableElement param, Messager messager) {
TypeMirror typeMirror = param.asType();//获取参数类型
// Check for generic type
if (typeMirror instanceof TypeVariable) {
TypeMirror upperBound = ((TypeVariable) typeMirror).getUpperBound();
if (upperBound instanceof DeclaredType) {
if (messager != null) {
messager.printMessage(Diagnostic.Kind.NOTE, "Using upper bound type " + upperBound +
" for generic parameter", param);
}
typeMirror = upperBound;
}
}
return typeMirror;
}
private TypeElement getSuperclass(TypeElement type) {
if (type.getSuperclass().getKind() == TypeKind.DECLARED) {
TypeElement superclass = (TypeElement) processingEnv.getTypeUtils().asElement(type.getSuperclass());
String name = superclass.getQualifiedName().toString();
if (name.startsWith("java.") || name.startsWith("javax.") || name.startsWith("android.")) {
// Skip system classes, this just degrades performance
return null;
} else {
return superclass;
}
} else {
return null;
}
}
private String getClassString(TypeElement typeElement, String myPackage) {
PackageElement packageElement = getPackageElement(typeElement);
String packageString = packageElement.getQualifiedName().toString();
String className = typeElement.getQualifiedName().toString();
if (packageString != null && !packageString.isEmpty()) {
if (packageString.equals(myPackage)) {
className = cutPackage(myPackage, className);
} else if (packageString.equals("java.lang")) {
className = typeElement.getSimpleName().toString();
}
}
return className;
}
private String cutPackage(String paket, String className) {
if (className.startsWith(paket + '.')) {
// Don't use TypeElement.getSimpleName, it doesn't work for us with inner classes
return className.substring(paket.length() + 1);
} else {
// Paranoia
throw new IllegalStateException("Mismatching " + paket + " vs. " + className);
}
}
private PackageElement getPackageElement(TypeElement subscriberClass) {
Element candidate = subscriberClass.getEnclosingElement();
while (!(candidate instanceof PackageElement)) {
candidate = candidate.getEnclosingElement();
}
return (PackageElement) candidate;
}
private void writeCreateSubscriberMethods(BufferedWriter writer, List<ExecutableElement> methods,
String callPrefix, String myPackage) throws IOException {
for (ExecutableElement method : methods) {
List<? extends VariableElement> parameters = method.getParameters();
TypeMirror paramType = getParamTypeMirror(parameters.get(0), null);
TypeElement paramElement = (TypeElement) processingEnv.getTypeUtils().asElement(paramType);
String methodName = method.getSimpleName().toString();
String eventClass = getClassString(paramElement, myPackage) + ".class";
Subscribe subscribe = method.getAnnotation(Subscribe.class);
List<String> parts = new ArrayList<>();
parts.add(callPrefix + "(\"" + methodName + "\",");
String lineEnd = "),";
if (subscribe.priority() == 0 && !subscribe.sticky()) {
if (subscribe.threadMode() == ThreadMode.POSTING) {
parts.add(eventClass + lineEnd);
} else {
parts.add(eventClass + ",");
parts.add("ThreadMode." + subscribe.threadMode().name() + lineEnd);
}
} else {
parts.add(eventClass + ",");
parts.add("ThreadMode." + subscribe.threadMode().name() + ",");
parts.add(subscribe.priority() + ",");
parts.add(subscribe.sticky() + lineEnd);
}
writeLine(writer, 3, parts.toArray(new String[parts.size()]));
if (verbose) {
processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "Indexed @Subscribe at " +
method.getEnclosingElement().getSimpleName() + "." + methodName +
"(" + paramElement.getSimpleName() + ")");
}
}
}
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
}
}
}
}
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");
}
}
}
private boolean isVisible(String myPackage, TypeElement typeElement) {
Set<Modifier> modifiers = typeElement.getModifiers();
boolean visible;
if (modifiers.contains(Modifier.PUBLIC)) {
visible = true;
} else if (modifiers.contains(Modifier.PRIVATE) || modifiers.contains(Modifier.PROTECTED)) {
visible = false;
} else {
String subscriberPackage = getPackageElement(typeElement).getQualifiedName().toString();
if (myPackage == null) {
visible = subscriberPackage.length() == 0;
} else {
visible = myPackage.equals(subscriberPackage);
}
}
return visible;
}
private void writeLine(BufferedWriter writer, int indentLevel, String... parts) throws IOException {
writeLine(writer, indentLevel, 2, parts);
}
private void writeLine(BufferedWriter writer, int indentLevel, int indentLevelIncrease, String... parts)
throws IOException {
writeIndent(writer, indentLevel);
int len = indentLevel * 4;
for (int i = 0; i < parts.length; i++) {
String part = parts[i];
if (i != 0) {
if (len + part.length() > 118) {
writer.write("\n");
if (indentLevel < 12) {
indentLevel += indentLevelIncrease;
}
writeIndent(writer, indentLevel);
len = indentLevel * 4;
} else {
writer.write(" ");
}
}
writer.write(part);
len += part.length();
}
writer.write("\n");
}
private void writeIndent(BufferedWriter writer, int indentLevel) throws IOException {
for (int i = 0; i < indentLevel; i++) {
writer.write(" ");
}
}
}