会了基本的EventBus的使用后 , 是不是感觉乍一看和广播有点像 ? 接下来我们八一八源码, 瞅一眼它的内部实现
提示 : 不要被庞大的代码量吓到 , 慢慢来其实也不复杂
EventBus -- 基本使用
EventBus源码 -- 注册
EventBus源码 -- 发送消息
EventBus源码 -- 注销
EventBus的注册
EventBus.getDefalt().regist(this)
这一句话就完成了EventBus的注册.
- 首先查看getDefalt()方法:
public static EventBus getDefault() {
if (defaultInstance == null) {
synchronized (EventBus.class) {
if (defaultInstance == null) {
defaultInstance = new EventBus();
}
}
}
return defaultInstance;
}
这里使用了双重校验的单例模式 , 获取到了一个EventBus的实例 . 在初始化有用到了new EventBus()
这个方法, 我们再来看看这个构造函数 .
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);
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;
}
这些都是各种对象的实例化.
- 拿到实例之后, 使用regist(this)进行注册
public void register(Object subscriber) {
Class> subscriberClass = subscriber.getClass(); //首先获取到订阅者的Class对象 , 就是注册的位置.
// 接下来在方法中遍历, 获取订阅方法<点进去>
List subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
synchronized (this) {
for (SubscriberMethod subscriberMethod : subscriberMethods) {
// 进行订阅 , 将订阅方法和对应的订阅者保存起来 <最后看这个方法>
subscribe(subscriber, subscriberMethod);
}
}
}
接下来看findSubscriberMethods方法 , 该方法从订阅类中获取到了所有的订阅信息 .
List findSubscriberMethods(Class> subscriberClass) {
// 以订阅者为key , 在缓存中读取订阅者方法
List subscriberMethods = METHOD_CACHE.get(subscriberClass);
if (subscriberMethods != null) {
return subscriberMethods;
}
// 缓存中没有方法时
if (ignoreGeneratedIndex) {
// 通过反射来获取
subscriberMethods = findUsingReflection(subscriberClass);
} else {
//通过注解获取 , 一般使用这种方法 <点进去>
subscriberMethods = findUsingInfo(subscriberClass);
}
// 如果集合仍然为空 . 说明在订阅者里面没有写订阅方法 , 或者订阅方法不是public , 这也说明了上文中 ,
// 订阅方法必须为public
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;
}
}
在看如何通过注解来获取: findUsingInfo
private List findUsingInfo(Class> subscriberClass) {
// 准备一个查找状态池 , 用"池"来优化查找速率
FindState findState = prepareFindState();
// 对查找状态池初始化
findState.initForSubscriber(subscriberClass);
//默认为null
while (findState.clazz != null) {
findState.subscriberInfo = getSubscriberInfo(findState);
if (findState.subscriberInfo != null) {
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);
}
获取订阅方法findUsingReflectionInSingleClass
这个方法就不贴代码了(毕竟不太懂注解的东西) , 大致过程就是:
- 首先通过反射订阅者所有的方法 , 如果没有方法就获取全部方法 , 并保存在方法数组中 .
- 然后遍历获取到的方法, 过滤掉非公有的方法后, 获取公有方法的参数类型 , 参数长度必须为1
- 检验是否含有@Subscribe的注解
- 校验该方法是否已添加到总线方法集合中, 如没有 , 就通过方法查找池添加到订阅方法集合中
所以在这里现总结一下订阅方法的要求 :
公有 , 参数长度为1 , 有@Subscribe的注解
至此 , 在注册的过程中就获取到了订阅者的所有方法, 然后我们在看订阅方法和订阅者的订阅过程 : subscribe(subscriber, subscriberMethod);
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
Class> eventType = subscriberMethod.eventType;
Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
CopyOnWriteArrayList 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;
}
}
List> subscribedEvents = typesBySubscriber.get(subscriber);
if (subscribedEvents == null) {
subscribedEvents = new ArrayList<>();
typesBySubscriber.put(subscriber, subscribedEvents);
}
subscribedEvents.add(eventType);
if (subscriberMethod.sticky) {
if (eventInheritance) {
// Existing sticky events of all subclasses of eventType have to be considered.
// Note: Iterating over all events may be inefficient with lots of sticky events,
// thus data structure should be changed to allow a more efficient lookup
// (e.g. an additional map storing sub classes of super classes: Class -> List).
Set, Object>> entries = stickyEvents.entrySet();
for (Map.Entry, 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);
}
}
}
不在代码上一一标注了 . 从上到下大致的来说一下子.
- 传进来的参数 , 第一个是订阅者 , 第二个是订阅方法 , 可以再返回去看一下 , 这个方法是for循环中的 , 针对每一个订阅方法都进行一次订阅 .
- 获取订阅方法的事件类型(参数类型) , 根据订阅的事件类型获取所有的订阅者
- 将订阅者添加到subscriptionsByEventType集合中 , 这个集合存放的是事件类型和订阅方法的映射
- 接下来针对订阅方法的优先级(priority)进行排序
- 获取该订阅者中的所有订阅方法的事件类型 , 添加到订阅事件集合中.
- 粘性事件的处理(还没看)
总结
其实EventBus的注册就是
- 通过反射获取到所有的订阅方法
- 将订阅者添加到EventBus总的事件订阅者集合中
- 将订阅者所有的订阅事件类型添加到typesBySubscriber中
再搞清楚两个集合的作用:
- subscriptionsByEventType: 事件类型与订阅者的映射
- typesBySubscriber : 订阅者和订阅类型的映射
吐槽一下: map的命名方式真反人类