看文章前提一句,重点看代码里面注释
一.EventBus是什么?
EventBus是一款针对Android优化的发布/订阅事件总线
二.How to Use?
//就这几个方法,不再赘述,默认你用过
fun onCreate() {
EventBus.getDefault().register(this)
}
fun onDestory() {
EventBus.getDefault().unregister(this)
}
fun send() {
EventBus.getDefault().post(DemoEvent())
}
@Subscribe
public fun onReceiveDemoEvent(event: DemoEvent) {
//balabala
}
三.源码解析(针对3.1.1版本)
1.EventBus.getDefault().register(Object) 注册EventBus
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);
}
}
}
subscriberMethodFinder 对象从哪里来?
先从构建说起,反手就是一个建造者模式
public class EventBusBuilder {
//EventBus的线程池,无限大,可复用
private final static ExecutorService DEFAULT_EXECUTOR_SERVICE = Executors.newCachedThreadPool();
//布尔值全部为标志位,跟你平时加flag执行不同逻辑一样,不需要特地理解,看具体用法
boolean logSubscriberExceptions = true;
boolean logNoSubscriberMessages = true;
boolean sendSubscriberExceptionEvent = true;
boolean sendNoSubscriberEvent = true;
boolean throwSubscriberException;
boolean eventInheritance = true;
boolean ignoreGeneratedIndex;
boolean strictMethodVerification;
ExecutorService executorService = DEFAULT_EXECUTOR_SERVICE;
//这玩意儿没用到,
List<Class<?>> skipMethodVerificationForClasses;
//通过APT注解,在编译时就生成对应解析注解为优化方式,这个默认为空,即你找不到
List<SubscriberInfoIndex> subscriberInfoIndexes;
//写日志的玩意儿
Logger logger
//内部就2个方法,判断是否为主线程,创建handler(作者给这些handler起名叫poster发射器)
MainThreadSupport mainThreadSupport;
......
}
//获取单例
public static EventBus getDefault() {
if (defaultInstance == null) {
synchronized (EventBus.class) {
if (defaultInstance == null) {
defaultInstance = new EventBus();
}
}
}
return defaultInstance;
}
//虽然 public ,别调用,没啥用
public EventBus() {
this(DEFAULT_BUILDER);
}
//就是各种赋值,赋值,
EventBus(EventBusBuilder builder) {
logger = builder.getLogger();
//一些事件集合哈,发送的事件就是往这里的,说到底还是往map里面存
subscriptionsByEventType = new HashMap<>();
typesBySubscriber = new HashMap<>();
stickyEvents = new ConcurrentHashMap<>();
//3种发射器,区别后面讲
mainThreadSupport = builder.getMainThreadSupport();
mainThreadPoster = mainThreadSupport != null ? mainThreadSupport.createPoster(this) : null;
backgroundPoster = new BackgroundPoster(this);
asyncPoster = new AsyncPoster(this);
indexCount = builder.subscriberInfoIndexes != null ? builder.subscriberInfoIndexes.size() : 0;
//重点看看这个,把他拉出来
subscriberMethodFinder = new SubscriberMethodFinder(builder.subscriberInfoIndexes,
builder.strictMethodVerification, builder.ignoreGeneratedIndex);
//后面这些就不讲了,就是各种flag的赋值,然后把线程池给单例
logSubscriberExceptions = builder.logSubscriberExceptions;
logNoSubscriberMessages = builder.logNoSubscriberMessages;
sendSubscriberExceptionEvent = builder.sendSubscriberExceptionEvent;
sendNoSubscriberEvent = builder.sendNoSubscriberEvent;
throwSubscriberException = builder.throwSubscriberException;
eventInheritance = builder.eventInheritance;
executorService = builder.executorService;
}
SubscriberMethodFinder 字面意思,订阅方法的查找器
SubscriberMethodFinder(List<SubscriberInfoIndex> subscriberInfoIndexes, boolean strictMethodVerification,boolean ignoreGeneratedIndex)
参数作用
1.subscriberInfoIndexes 这个呢其实就是apt的插件生成的一些EventBusIndex,注入进去
2.strictMethodVerification 默认值false,如果为true,会抛异常哈。具体点到这个类看看就可以
3.ignoreGeneratedIndex 忽略注解,仅通过反射方式拿取,默认false哈,就是会去找index那种
下面看看这个类里面的方法,回到主题
一开始讲的这个EventBus.getDefault().register(XXX)方法里面
public void register(Object subscriber) {
Class<?> subscriberClass = subscriber.getClass();
List<SubscriberMethod> subscriberMethods =
//看这里这里
subscriberMethodFinder.findSubscriberMethods(subscriberClass);
synchronized (this) {
for (SubscriberMethod subscriberMethod : subscriberMethods) {
subscribe(subscriber, subscriberMethod);
}
}
}
也就是这个方法 findSubscriberMethods
List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
//有缓存直接取了哈。METHOD_CACHE又是一个hashMap
List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);
if (subscriberMethods != null) {
return subscriberMethods;
}
if (ignoreGeneratedIndex) {
//刚才说过的,开了ignoreGeneratedIndex就直接用反射了
subscriberMethods = findUsingReflection(subscriberClass);
} else {
//findUsingInfo 这个方法是真正根据要订阅的类查找订阅方法了
subscriberMethods = findUsingInfo(subscriberClass);
}
if (subscriberMethods.isEmpty()) {
//这里提一嘴,平时你们写了register但是类里又没有Subscribe注解,你App就炸了,这里报的
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;
}
}
找到findUsingInfo这个方法
private List<SubscriberMethod> findUsingInfo(Class<?> subscriberClass) {
FindState findState = prepareFindState();//准备一个查找的state
findState.initForSubscriber(subscriberClass);//根据当前类初始化 链接1
while (findState.clazz != null) {
findState.subscriberInfo = getSubscriberInfo(findState);//从subscriberInfoIndexes里面找方法,链接2
if (findState.subscriberInfo != null) {
//subscriberInfo 这个里面有方法名什么的,就是提前已经根据注解解析完了
SubscriberMethod[] array = findState.subscriberInfo.getSubscriberMethods();
for (SubscriberMethod subscriberMethod : array) {
//检查添加方法,这里面会抛出异常,总之不要有同名方法。没问题就是add
if (findState.checkAdd(subscriberMethod.method, subscriberMethod.eventType)) {
findState.subscriberMethods.add(subscriberMethod);
}
}
} else {
//没找到只好用反射的方式了。。链接3
findUsingReflectionInSingleClass(findState);
}
findState.moveToSuperclass();
}
//最后把订阅好的方法,返回去。然后回收findState。就是考虑复用。。
return getMethodsAndRelease(findState);
}
//相关方法哈.看title找下把
//链接1
void initForSubscriber(Class<?> subscriberClass) {
this.subscriberClass = clazz = subscriberClass;
skipSuperClasses = false;
subscriberInfo = null;
}
//链接2
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;
}
}
if (subscriberInfoIndexes != null) {
//这里看到了么。。眼熟的subscriberInfoIndexes ,就是apt注解提前生成的类里,遍历去找
for (SubscriberInfoIndex index : subscriberInfoIndexes) {
SubscriberInfo info = index.getSubscriberInfo(findState.clazz);
if (info != null) {
return info;
}
}
}
return null;
}
//链接3 这就是个反射。先根据类,获取注解,然后解析。后面一样的。。也是查找下是不是有,然后添加添加。
//2.X版本方式。。以前人们不是天天说,反射,影响效率么,所以现在用原则上用上面那个效率高。
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);
if (subscribeAnnotation != null) {
Class<?> eventType = parameterTypes[0];
if (findState.checkAdd(method, eventType)) {
ThreadMode threadMode = subscribeAnnotation.threadMode();
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");
}
}
}
拿到订阅的方法之后,要跟对象绑定起来,在register的方法的遍历里
subscribe(subscriber, subscriberMethod);
参数1就是你register的传进来的对象,参数2是这个对象类里面找到的方法
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
//这里开始,是先去把方法放到subscriptionsByEventType 这个事件类型的缓存
Class<?> eventType = subscriberMethod.eventType;
Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
if (subscriptions == null) {
subscriptions = new CopyOnWriteArrayList<>();
subscriptionsByEventType.put(eventType, subscriptions);
} else {
if (subscriptions.contains(newSubscription)) {
throw new EventBusException("Subscriber " + subscriber.getClass() + " already registered to event "
+ eventType);
}
}
int size = subscriptions.size();
for (int i = 0; i <= size; i++) {
if (i == size || subscriberMethod.priority > subscriptions.get(i).subscriberMethod.priority) {
subscriptions.add(i, newSubscription);
break;
}
}
//typesBySubscriber这个就是isRegister,unRegister使用的哈。
List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);
if (subscribedEvents == null) {
subscribedEvents = new ArrayList<>();
typesBySubscriber.put(subscriber, subscribedEvents);
}
subscribedEvents.add(eventType);
//以下就是stikyEvent相关,checkPostStickyEventToSubscription,如果本地有粘性事件
//注册粘性事件的时候一并取了
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);
}
}
}
断点看实际效果,可以看到通过subscriberMethodFinder 找到的SubscriberMethod有参数名,对应方法,线程模式等等
SubscriberMethod.png
再看 subscriptionsByEventType 缓存的对象,就是把事件类型作为key,前面所拿到的Subscription作为value,进行缓存
subscriptionsByEventType.png
最后看typesBySubscriber缓存的对象,就是把object作为key,该object订阅对应的事件类型作为value
typesBySubscriber.png
2.EventBus.getDefault().unregister(Object) 解注册EventBus
public synchronized void unregister(Object subscriber) {
//subscribedTypes register的时候往这个里面放过,解注册的时候移除
List<Class<?>> subscribedTypes = typesBySubscriber.get(subscriber);
if (subscribedTypes != null) {
for (Class<?> eventType : subscribedTypes) {
//这个遍历的for循环里面,把对应的事件全部移除了噢
unsubscribeByEventType(subscriber, eventType);
}
typesBySubscriber.remove(subscriber);
} else {
logger.log(Level.WARNING, "Subscriber ...: " + subscriber.getClass());
}
}
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--;
}
}
}
}
3.EventBus.getDefault().post(EventObject())发送事件
最后一步了,发送事件
public void post(Object event) {
//currentPostingThreadState 这个是ThreadLocal,可以看作数据结构map,key为线程,value为你设定的对象,每个线程不同。
PostingThreadState postingState = currentPostingThreadState.get();
List<Object> eventQueue = postingState.eventQueue;
eventQueue.add(event);
if (!postingState.isPosting) {
postingState.isMainThread = isMainThread();
postingState.isPosting = true;
if (postingState.canceled) {
throw new EventBusException("Internal error. Abort state was not reset");
}
try {
while (!eventQueue.isEmpty()) {
//遍历发送事件
postSingleEvent(eventQueue.remove(0), postingState);
}
} finally {
postingState.isPosting = false;
postingState.isMainThread = false;
}
}
}
private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {
.........
//回调这个方法
subscriptionFound = postSingleEventForEventType(event, postingState, eventClass);
........
}
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) {
//取出对应的事件跟subscription
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;
}
POSTING,MAIN,MAIN_ORDERED,这些就是订阅事件的线程模式
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 MAIN_ORDERED:
if (mainThreadPoster != null) {
mainThreadPoster.enqueue(subscription, event);
} else {
// temporary: technically not correct as poster not decoupled from subscriber
invokeSubscriber(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);
}
}
关于poster,其实就是一开始创建的线程池中取出线程来运行,其中比较特殊的是mainThreadPoster,这个其实是handler,把mainLooper取出来给他,创建出来的
Object getAndroidMainLooperOrNull() {
try {
return Looper.getMainLooper();
} catch (RuntimeException e) {
// Not really a functional Android (e.g. "Stub!" maven dependencies)
return null;
}
}
class AndroidHandlerMainThreadSupport implements MainThreadSupport {
private final Looper looper;
...
@Override
public Poster createPoster(EventBus eventBus) {
return new HandlerPoster(eventBus, looper, 10);//这里
}
}
//最初的构造者模式中,对应的地方。
EventBus(EventBusBuilder builder) {
......
mainThreadSupport = builder.getMainThreadSupport();
mainThreadPoster = mainThreadSupport != null ? mainThreadSupport.createPoster(this) : null;
.....
}
最后来看看invokeSubscriber(Subscription subscription, Object event)
void invokeSubscriber(Subscription subscription, Object event) {
try {
//其实就是调用method的invoke方法,其中subscription.subscriber是订阅对象,event是对应发送的事件
subscription.subscriberMethod.method.invoke(subscription.subscriber, event);
} catch (InvocationTargetException e) {
handleSubscriberException(subscription, event, e.getCause());
} catch (IllegalAccessException e) {
throw new IllegalStateException("Unexpected exception", e);
}
}