先介绍一下写这篇文章的背景,因为几乎每个项目中都使用到了EventBus,但是对它的理解仅仅在于如何使用,而不知其详细由来(当然以前还是知道个大概!),俗话说的好:“授人以鱼不如授人以渔”,今天让我这个老菜鸟来学习一下渔术!!!
什么是EventBus
EventBus翻译过来是事件总线的意思,官方对其描述由一张图即可说明其作用是不是很清晰呢!
简单的翻译一下这张图,Subscriber订阅Event,并将Subscriber注册到事件总线(EventBus),Publisher发送Event并通过事件总线找到相应的Subscriber使其接收到相应Event。
EventBus的优点:
1.使用便捷:Subscriber只需定义public关键字的方法并已@Subscribe为注解即可订阅使用。
2.操作支持性强:通过@Subscribe可根据使用者的需要,定义ThreadMode、sticky、priority
EventBus的缺点:
.强引用:EventBus对Subscriber使用的是强引用,不再使用时需unRegister Subscriber
.订阅的事件多了以后会导致EventClass很多,使其比较难管理
.多个Subscriber订阅相同的Event,如果在主线程订阅的,处理不当可能会造成耗时严重时导致ANR
EventBus源码分析
1.EventBus初始化时做了什么
2.如何订阅
3.发送事件的时候做了什么
.EventBus初始化时做了什么
EventBus.getDefault()
//点进去查看源码
/** Convenience singleton for apps using a process-wide EventBus instance. */
public static EventBus getDefault() {
if (defaultInstance == null) {
synchronized (EventBus.class) {
if (defaultInstance == null) {
defaultInstance = new EventBus();
}
}
}
return defaultInstance;
}
EventBus.getDefault() 方法创建了一个实例,我们看看里面配置了哪些参数
...省略代码
private static final EventBusBuilder DEFAULT_BUILDER = new EventBusBuilder();
...省略代码
/**
* Creates a new EventBus instance; each instance is a separate scope in which events are delivered. To use a
* central bus, consider {@link #getDefault()}.
*/
public EventBus() {
this(DEFAULT_BUILDER);
}
EventBus(EventBusBuilder builder) {
logger = builder.getLogger();
subscriptionsByEventType = new HashMap<>();
typesBySubscriber = new HashMap<>();
stickyEvents = new ConcurrentHashMap<>();
mainThreadSupport = builder.getMainThreadSupport();//内部逻辑是得到主线程的looper
mainThreadPoster = mainThreadSupport != null ? mainThreadSupport.createPoster(this) : null;//main poster
backgroundPoster = new BackgroundPoster(this);//backgroundPoster
asyncPoster = new AsyncPoster(this);//异步Poster
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;//内部创建了线程池,根据Subscriber订阅的Event的ThreadMode来执行哪一种Poster
}
EventBus通过建造者模式初始化的我们看看EventBusBuilder里面是怎么设置的
/**
* Creates EventBus instances with custom parameters and also allows to install a custom default EventBus instance.
* Create a new builder using {@link EventBus#builder()}.
*/
public class EventBusBuilder {
private final static ExecutorService DEFAULT_EXECUTOR_SERVICE = Executors.newCachedThreadPool();//创建了一个线程池
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;
List<SubscriberInfoIndex> subscriberInfoIndexes;
Logger logger;
MainThreadSupport mainThreadSupport;
EventBusBuilder() {
}
...省略代码
.如何订阅
接下来我们分析分析EventBus.register(Object subscriber) 方法里都做了什么
public void register(Object subscriber) {
Class<?> subscriberClass = subscriber.getClass();
List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);//查找订阅者订阅的事件(Method)
synchronized (this) {
for (SubscriberMethod subscriberMethod : subscriberMethods) {
subscribe(subscriber, subscriberMethod);//处理订阅
}
}
}
看看subscriberMethodFinder这个对象在创建EventBus时就初始化了 subscriberMethodFinder.findSubscriberMethods(Class<?> subscriberClass) 方法里面做了什么呢,直接拉出整段代码
class SubscriberMethodFinder {
...省略代码
SubscriberMethodFinder(List<SubscriberInfoIndex> subscriberInfoIndexes, boolean strictMethodVerification,
boolean ignoreGeneratedIndex) {
this.subscriberInfoIndexes = subscriberInfoIndexes;
this.strictMethodVerification = strictMethodVerification;
this.ignoreGeneratedIndex = ignoreGeneratedIndex;
}
List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);//先去缓存里面拿,最开始肯定是为空的,因为还没有存,所有接着往下走
if (subscriberMethods != null) {
//在缓存中拿大,返回订阅者订阅的方法
return subscriberMethods;
}
if (ignoreGeneratedIndex) {
//ignoreGeneratedIndex默认为false
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"