对于EventBus 想必作为安卓开发都不会陌生,这边也不会进行讲解使用方法,只是本人在准备面试重新又撸了一遍源码,回味而已,希望给各位看官意犹未尽的感觉。
原理图在此

带问题查看源码
当前看源码的时候肯定是带着问题看才能不会适可而止,所以我的问题如下:
1.register(),unregister()如何绑定?
2.@Subscribe 注解之后是不是用反射找到对应的方法?指定 theardMode 如何实现线程切换?
3.如何发送事件.粘性事件?
总结就是:如何绑定对应的事件,如果发送与接受事件
看源码如何入手
EventBus 查看源码相对于RxJava,Retrofit还是比较容易的,入口很明显
@Override
protected void onStart() {
super.onStart();
EventBus.getDefault().register(this);//绑定生命周期
}
@Override
protected void onStop() {
super.onStop();
EventBus.getDefault().register(this);//绑定生命周期
}
EventBus.getDefault().post(new MessageEvent("test"));
@Subscribe(threadMode = ThreadMode.MAIN)
public void testEventBus(Message message){
System.out.println(message.msg);
}
1. EventBus.getDefault() 获取实例 EventBus.class
//获取静态的单例的实例对象
static volatile EventBus defaultInstance;
public static EventBus getDefault() {
if (defaultInstance == null) {
synchronized (EventBus.class) {
if (defaultInstance == null) {
defaultInstance = new EventBus();
}
}
}
return defaultInstance;
}
这种单例好像是非常流行的写法:volatile 关键字声明 以及进行双重效验有啥好处?我的理解:
- 第一个if判断可以在多个线程进入方法的时候过滤掉不为Null的线程,直接返回单实例。
- 为空的线程到第二个线程由于同步锁的原因只能进行一次初始化,相当于只能由一个线程进入锁中进行实例化对象。有点hashCode() 和 equal() 的味道。
//单例为什么是public ,我认为每个线程都能注册得到相应的EventBus事件总线,都是相互隔离的
public EventBus() {
this(DEFAULT_BUILDER);// EventBusBuilder 构建者模式
}
private static final EventBusBuilder DEFAULT_BUILDER = new EventBusBuilder(); //EventBusBuilder 构建者模式
//初始化 下面过滤了比较重要的内容,先有一个大概印象,我都是看到后面才发现这些东西的重要性
EventBus(EventBusBuilder builder) {
...
subscriptionsByEventType = new HashMap<>(); //通过存储的key(class)找到订阅者
typesBySubscriber = new HashMap<>();//注册之后会操作这个Map
stickyEvents = new ConcurrentHashMap<>();//粘性事件
mainThreadPoster = mainThreadSupport != null ? mainThreadSupport.createPoster(this) : null; //一个Handler
backgroundPoster = new BackgroundPoster(this); //一个线程
asyncPoster = new AsyncPoster(this); //一个线程
subscriberMethodFinder = new SubscriberMethodFinder(builder.subscriberInfoIndexes,
builder.strictMethodVerification, builder.ignoreGeneratedIndex); //@Subscriber注解方法找寻器
executorService = builder.executorService;//线程池
...
}
2.register()
public void register(Object subscriber) {
Class<?> subscriberClass = subscriber.getClass();
List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass); //通过查询器查找,进行添加到相应的方法订阅集合
synchronized (this) {
for (SubscriberMethod subscriberMethod : subscriberMethods) {
subscribe(subscriber, subscriberMethod);
}
}
}
subscriberMethodFinder.findSubscriberMethods 添加到相应的集合进行缓存
List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass); //缓存中获取
if (subscriberMethods != null) {
return subscriberMethods;
}
if (ignoreGeneratedIndex) {//默认是false
subscriberMethods = findUsingReflection(subscriberClass);
} else {
subscriberMethods = findUsingInfo(subscriberClass); //执行此处找到相应的subscriberMethods 进行添加与返回
}
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<SubscriberMethod> findUsingInfo(Class<?> subscriberClass) {
FindState findState = prepareFindState();//prepareFindState 查找遍历旧的集合是否存在,不存在就创建新的FindState ,FindState 封装了集合进行保存相应的 class 与 method
findState.initForSubscriber(subscriberClass);
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); //通过反射 获取class 被注解的方法@Subscriber 然后添加到findState.subscriberMethods.add()
}
findState.moveToSuperclass();
}
return getMethodsAndRelease(findState); //返回与findState 资源释放
}
每个方法的订阅 subscribe()
public void register(Object subscriber) {
Class<?> subscriberClass = subscriber.getClass();
List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
synchronized (this) {
for (SubscriberMethod subscriberMethod : subscriberMethods) {
subscribe(subscriber, subscriberMethod);
}
}
}
subscribe 代码有点长,简要概述一下:通过判断subscriptionsByEventType typesBySubscriber 两个集合是否存在进行相应的操作,最后判断是否是粘性事件进行 checkPostStickyEventToSubscription
☆☆☆☆☆ 重点来了,事件分发 checkPostStickyEventToSubscription 调用 postToSubscription(newSubscription, stickyEvent, isMainThread());
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); 通过HandlerPoster 添加到队列中
}
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); //BackgroundPoster 遍历PendingPost中 pendingPostPool 集合里面的事件,每个事件都执行
} else {
invokeSubscriber(subscription, event);
}
break;
case ASYNC:
asyncPoster.enqueue(subscription, event);//AsyncPoster PendingPost中 pendingPostPool 集合里面的一个事件并执行。
break;
default:
throw new IllegalStateException("Unknown thread mode: " + subscription.subscriberMethod.threadMode);
}
}
post()
private final ThreadLocal<PostingThreadState> currentPostingThreadState = new ThreadLocal<PostingThreadState>() {
@Override
protected PostingThreadState initialValue() {
return new PostingThreadState();
}
};
public void post(Object event) {
PostingThreadState postingState = currentPostingThreadState.get(); // ThreadLocal 是不会让其他线程共享的,线程独有的
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;
}
}
}
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);//找到订阅的方法 遍历之前register 中 集合 subscriptionsByEventType (存着可以为class ,value 为mothod),进行遍历postToSubscription
}
if (!subscriptionFound) {
if (logNoSubscriberMessages) {
logger.log(Level.FINE, "No subscribers registered for event " + eventClass);
}
if (sendNoSubscriberEvent && eventClass != NoSubscriberEvent.class &&
eventClass != SubscriberExceptionEvent.class) {
post(new NoSubscriberEvent(this, event)); //
}
}
}
至此:EventBus 的基本事件完结,由于篇幅过程,Sticky后续讲解
总结:EventBus
1.EventBus 通过双重效验进行返回单实例对象,通过EventBusBuilder 构造者模式进行初始化一些重要参数,例如以下 Poster,SubscriberMethodFinder方法查询器,存放方法注解的集合subscriptionsByEventType等,值得注意的是一些封装类 SubscriberMethod,FindState
2.register 把保存在集合中的所有事件进行订阅 放到相应的队列中
3.post方法进行从队列中获取,通过handler进行事件的发送
本人水平有限,如有不对的地方,欢迎指正,共同进步
网友评论