android开源框架分析系列之-EventBus
最近在看开源框架,对于经常使用的EventBus,觉得用起来非常简单,所以比较好奇,看了几篇文章。然后把EventBus的关键点提取到了Anki上,随着时间的推移,突然发现印象越来越模糊,反反复复的看光是看理论印象还是不够深刻。于是,打算深挖一下EventBus的源码。
开篇习惯,带着问题看源码,如果你能回答出如下问题,那么,出门右转,不要浪费宝贵的大好青春~
1.简单的描述一个EventBus的使用Demo?
2.EventBus的注册是怎么回事?
3.当我使用PostEvent发送事件之后,EventBus会执行哪些流程?它是如何找到对应的事件的?
4.EventBus的取消注册是怎么回事?
5.简单的说一下粘性事件?
#关于EventBus
EventBus的简介,网上有的是,这里不再赘述,你只要知道,它使用的是观察者模式,通过Event来传递。
#带着问题看源码
##简单的描述一个EventBus的使用Demo?
###注册
EventBus.getDefault().register(this);
###自定义事件
public class MessageEvent{
private String message;
public MessageEvent(String message){
this.message=message;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
###发送
EventBus.getDefault().post(messageEvent);
###处理事件
@Subscribe(threadMode = ThreadMode.MAIN)
public void XXX(MessageEvent messageEvent) {
...
}
###取消注册
EventBus.getDefault().unRegister(this);
##EventBus的注册是怎么回事?
接下来就带你看看注册的源码是怎么回事,先回忆一下上一节的代码,我们就使用了一句简单的EventBus.getDefault().register(this);就完成了注册,它主要分为两个部分:getDefault()和register(this);
那么getDefault是什么呢?
查看源代码得知,原来它就是一个使用了volatile和synchronized双重锁单例:
static volatile EventBus defaultInstance;
public static EventBus getDefault() {
EventBus instance = defaultInstance;
if (instance == null) {
synchronized (EventBus.class) {
instance = EventBus.defaultInstance;
if (instance == null) {
instance = EventBus.defaultInstance = new EventBus();
}
}
}
return instance;
}
这里面还有一个小技巧:
/**
* 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);
}
public static EventBusBuilder builder() {
return new EventBusBuilder();
}
发现没,它是在单例的EventBus里面,默认设置了一个EventBusBuilder,通过EventBusBuilder的名字你大概能轻易的猜出来使用了构建者模式,最终返回的这个真正的EventBus。
在得到单例之后,就进行了注册:
下面就是注册方法:
注册的时候要注意,首先使用注册就一定要使用反注册,否则,你将会一直收到该消息;然后是一定要为处理该消息的方法进行声明,Subscribe也行,或者是再加上ThreadMode和优先级;
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注解的事件:
注册的时候,会获取你注册的类对象,然后调用findSubscriberMethods方法,返回List
这里面用到了一个METHOD_CACHE,它是一个ConcurrentHashMap,考考你:什么是ConcurrentHashMap?它是如何使用size()方法如何容器大小的?
List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
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;
}
}
然后接下来就是findUsingReflection
#参考文章
https://www.jianshu.com/p/f9ae5691e1bb