EventBus是一个事件发布/订阅总线,有效适用于Android系统平台。
EventBus优点
- 组件之间的通信更加简单
- 事件的发送者和接受者之间充分解耦
- 非常好的运用在Activitys、Fragments和后台线程
- 避免复杂和易出错的依赖性和生命周期问题
- 代码更加简单
- 快
- 小
EventBus个人总结
register:通过反射或apt方式获取当前订阅者的所有订阅方法
post:根据发送的订阅事件,获取到指定订阅者,再根据threadMode类型,去指定线程中执行订阅方法
unregister:取消当前订阅者订阅
源码解析
register注册
EventBus.getDefault().register(this);
getDefault方法
public static EventBus getDefault() {
if (defaultInstance == null) {
synchronized (EventBus.class) {
if (defaultInstance == null) {
defaultInstance = new EventBus();
}
}
}
return defaultInstance;
}
EvnetBus是单例对象,采用双重校验方式,防止多线程并发问题。在EvnetBus构造函数中初始化EventBusBuilder对象(通过建造者模式进行创建的),主要初始化存放订阅者、订阅方法、订阅事件的Map和Poster及一些状态信息
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);
}
}
}
subscriber: Activity或Fragment对象,就是后边所说的订阅者
subscriberClass:订阅者的Class对象
subscriberMethodFinder:获取或查找订阅者Method的对象
subscriberMethods:存放订阅者中订阅方法的列表
这里就是把订阅者订阅的方法找出来,并保存到subscriberMethods集合中,再通过循环的方式,把订阅者和订阅者中的订阅方法封装到subscriptionsByEventType中
findSubscriberMethods方法
List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
//先缓存获取订阅者的订阅方法
List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);
if (subscriberMethods != null) {
return subscriberMethods;
}
/**
* ignoreGeneratedIndex 为true则表明用反射生成 subscriberMethods
* false则使用apt获取 subscriberMethods(默认false)
*/
if (ignoreGeneratedIndex) {
//通过反射获取subscriberMethods
subscriberMethods = findUsingReflection(subscriberClass);
} else {
//如果没有配置MyEventBusIndex,依然会通过反射获取subscriberMethods
subscriberMethods = findUsingInfo(subscriberClass);
}
//注册了EvnetBus的订阅者,就必须有订阅方法,否则就会这个报错
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;
}
}
METHOD_CACHE: ConcurrentHashMap采用分段锁的设计,存放的是订阅者和订阅者中的订阅方法列表
即key:订阅者的Class对象,value:订阅者中的订阅方法列表
ignoreGeneratedIndex:默认是false
这里就是获取到订阅者中的所有订阅方法,如果缓存中有则从缓存中取,没有则通过反射或apt方式获取到所有订阅方法
findUsingInfo方法
private List<SubscriberMethod> findUsingInfo(Class<?> subscriberClass) {
//从FindState池中获取FindState对象
FindState findState = prepareFindState();
//初始化FindState对象
findState.initForSubscriber(subscriberClass);
//while循环查找订阅方法
while (findState.clazz != null) {
//如果没有配置MyEventBusIndex,则subscriberInfo为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 {
//如果没有配置MyEventBusIndex,则通过反射查找订阅方法
findUsingReflectionInSingleClass(findState);
}
//进入父类继续查找订阅方法
findState.moveToSuperclass();
}
//回收FindState,并返回订阅者的订阅方法列表
return getMethodsAndRelease(findState);
}
subscriberClass:订阅者的Class对象
findState:保存订阅者及订阅方法的信息
先判断是否配置了MyEventBusIndex,没有则通过反射查找当前类的订阅方法,然后再进入父类继续查找订阅方法,把查找到的所有订阅方法封装到FindState类的subscriberMethods集合中,最后回收FindState
prepareFindState方法
private FindState prepareFindState() {
synchronized (FIND_STATE_POOL) {
for (int i = 0; i < POOL_SIZE; i++) {
FindState state = FIND_STATE_POOL[i];
if (state != null) {
FIND_STATE_POOL[i] = null;
return state;
}
}
}
return new FindState();
}
先初始化大小为4的FindState数组,通过循环从数组中拿到不为空的FindState对象,进行回收利用,如果全为空,则创建对象。
getMethodsAndRelease方法
private List<SubscriberMethod> getMethodsAndRelease(FindState findState) {
List<SubscriberMethod> subscriberMethods = new ArrayList<>(findState.subscriberMethods);
findState.recycle();
synchronized (FIND_STATE_POOL) {
for (int i = 0; i < POOL_SIZE; i++) {
if (FIND_STATE_POOL[i] == null) {
FIND_STATE_POOL[i] = findState;
break;
}
}
}
return subscriberMethods;
}
从FindState中拿到订阅者的订阅方法,并返回,再把使用过的FindState对象进行回收
疑问?
prepareFindState和getMethodsAndRelease方法配合使用,定义了FindState大小为4的数组,但是感觉只会用到FindState[0],其他感觉不会用到?
findUsingReflectionInSingleClass方法
通过反射来查找订阅方法
private void findUsingReflectionInSingleClass(FindState findState) {
Method[] methods;
try {
//getMethods只能拿到public方法(包括继承的类或接口的方法)
//getDeclaredMethods方法能拿到所有(包括接口但不包括继承的方法)方法
methods = findState.clazz.getDeclaredMethods();
} catch (Throwable th) {
methods = findState.clazz.getMethods();
findState.skipSuperClasses = true;
}
for (Method method : methods) {
//获取订阅方法的类型
int modifiers = method.getModifiers();
//是public且非static、abstract、BRIDGE、SYNTHETIC方法则进入
if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) {
//获取订阅方法内的参数
Class<?>[] parameterTypes = method.getParameterTypes();
//只有一个参数的进入
if (parameterTypes.length == 1) {
//查找包含Subscribe注解
Subscribe subscribeAnnotation = method.getAnnotation(Subscribe.class);
//如果不为空,则说明是订阅者订阅了EvnetBus的方法,否则就不是
if (subscribeAnnotation != null) {
//获取订阅方法内第一个参数的字节码对象
Class<?> eventType = parameterTypes[0];
//校验是否添加该方法
if (findState.checkAdd(method, eventType)) {
//获取注解上定义的线程模式
ThreadMode threadMode = subscribeAnnotation.threadMode();
//把订阅方法、订阅方法内参数的class对象、threeadMode线程模式、优先级大小、是否接受粘性事件封装到SubscriberMethod对象中,并添加到存放订阅方法的List中
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)) {
//提示订阅方法必须是public修饰的
String methodName = method.getDeclaringClass().getName() + "." + method.getName();
throw new EventBusException(methodName +
" is a illegal @Subscribe method: must be public, non-static, and non-abstract");
}
}
}
1:通过反射来获取订阅者中的所有方法
2:根据方法的类型、参数、注解找到所有订阅方法
3:把订阅方法、订阅方法内参数的class对象、threeadMode线程模式、优先级大小、是否接受粘性事件封装到SubscriberMethod对象中,并添加到FindState对象的subscriberMethods列表中
checkAdd方法
boolean checkAdd(Method method, Class<?> eventType) {
//两层检查:第一层根据EventType,第二层根据签名
Object existing = anyMethodByEventType.put(eventType, method);
if (existing == null) {
return true;
} else {
if (existing instanceof Method) {
//如果父类和子类订阅方法和参数相同返回false,否则返回true
if (!checkAddWithMethodSignature((Method) existing, eventType)) {
// Paranoia check
throw new IllegalStateException();
}
//放置FindState对象,使其再次不进入if (existing instanceof Method)方法
anyMethodByEventType.put(eventType, this);
}
return checkAddWithMethodSignature(method, eventType);
}
}
注意
当报IllegalStateException错误时,则优先查看父类和子类是否有相同的订阅方法和参数
checkAddWithMethodSignature方法
private boolean checkAddWithMethodSignature(Method method, Class<?> eventType) {
methodKeyBuilder.setLength(0);
methodKeyBuilder.append(method.getName());
methodKeyBuilder.append('>').append(eventType.getName());
//methodKey:方法的名字+'>'+参数的名字
String methodKey = methodKeyBuilder.toString();
//获取方法所在类的字节码对象
Class<?> methodClass = method.getDeclaringClass();
//如果key之前存在,则返回之前存放的value
Class<?> methodClassOld = subscriberClassByMethodKey.put(methodKey, methodClass);
//如果传递过来的methodClass是父类,methodClassOld是子类,则进入else
//如果父类和子类订阅方法和参数相同则肯定会进入else,否则进入if
if (methodClassOld == null || methodClassOld.isAssignableFrom(methodClass)) {
return true;
} else {
subscriberClassByMethodKey.put(methodKey, methodClassOld);
return false;
}
}
isAssignableFrom:用来判断一个类Class1和另一个类Class2是否相同或是Class2类的超类或接口
1:第一次检查根据eventType参数类的字节码,判断是否存在,不存在则返回true,并添加此订阅方法,存在则进入第二次检查
2:第二次检查则先把前一次保存的方法名和方法内的参数类名组合成key,把方法所在的类名定义成value存放到HashMap中
—>如果methodClassOld等于null或者methodClassOld和methodClass相等或者是methodClass的父类则进入,否则进入到else并抛异常。
—>如果父类和子类订阅方法和参数相同则肯定会进入else抛异常,否则进入if添加订阅方法
目的:如果父类订阅了此方法,子类就不需要再重新订阅了,因为可以直接继承过来
以上就是findSubscriberMethods方法内所做的操作,主要作用就是拿到订阅者中所有订阅方法
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);
}
}
}
subscribe方法
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
//获取订阅方法中参数的Class对象
Class<?> eventType = subscriberMethod.eventType;
//创建一个Subscription来保存订阅者和订阅方法
Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
//根据订阅方法的事件类型获取特定的Subscription
CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
if (subscriptions == null) {
subscriptions = new CopyOnWriteArrayList<>();
subscriptionsByEventType.put(eventType, subscriptions);
} else {
//如果不为null,并且包含了这个newSubscription,那么说明该subscriber已经注册了该事件,抛出异常
if (subscriptions.contains(newSubscription)) {
throw new EventBusException("Subscriber " + subscriber.getClass() + " already registered to event "
+ eventType);
}
}
//根据优先级把订阅事件添加到CopyOnWriteArrayList集合中
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<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);
if (subscribedEvents == null) {
subscribedEvents = new ArrayList<>();
//把订阅者、事件放进HashMap中
typesBySubscriber.put(subscriber, subscribedEvents);
}
//添加订阅方法内参数的Class对象
subscribedEvents.add(eventType);
//粘性事件处理
.....省略.....
}
newSubscription:保存订阅者和订阅方法
subscriptionsByEventType: Key是订阅方法中事件类型的Class对象,value是存放Subscription的集合,在Subscription中保存着订阅者和订阅方法
typesBySubscriber:用于取消注册EventBus的HashMap,Key是订阅者对象,value是存放订阅方法内参数的Class对象的列表
总结
1:通过反射找到订阅者内的所有订阅方法
2:把订阅者和订阅方法封装Subscription对象里,再添加到CopyOnWriteArrayList集合中,再以订阅方法中事件类型的Class对象为key,CopyOnWriteArrayList为value存放到subscriptionsByEventType->HashMap中(发送事件时就是从此Map中取)
3:根据优先级把订阅事件添加到CopyOnWriteArrayList集合中
4:添加用于取消注册EvnetBus的HashMap
post发布订阅事件
public void post(Object event) {
//获取当前线程的PostingThreadState,即每个线程维护一份PostingThreadState对象
PostingThreadState postingState = currentPostingThreadState.get();
//获取事件队列
List<Object> eventQueue = postingState.eventQueue;//事件队列
//把当前事件插入到事件队列中
eventQueue.add(event);
if (!postingState.isPosting) {
postingState.isMainThread = isMainThread();//是否主线程
postingState.isPosting = true;//事件发布状态
if (postingState.canceled) {//是否取消post
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;
}
}
}
第一步:获取一个与当前线程关联的PostingThreadState对象,PostingThreadState对象主要是封装当前线程的一些状态、订阅者、订阅事件等信息
第二步:从PostingThreadState中获取事件队列,再把当前事件插入到事件队列中
第三步:循环处理队列中的所有事件
第9行是先判断事件是否正在发布,如果正在发布则isPosting为true,if语句就不会进入,但post方法会进入,然后把事件添加到事件队列中,此时第17行还是会循环处理队列中添加的事件
postSingleEvent方法
private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {
Class<?> eventClass = event.getClass();
boolean subscriptionFound = false;
//默认eventInheritance=true
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);
}
.....省略.....
}
这里是先从缓存中获取待发送事件类型的列表,用列表的目的就是要包括当前事件的父类和接口类,然后通过循环的方法发送事件
lookupAllEventTypes方法
private static List<Class<?>> lookupAllEventTypes(Class<?> eventClass) {
synchronized (eventTypesCache) {
//先从缓存中获取需要发送事件类型的列表,这个列表包括当前事件类及父类和接口
List<Class<?>> eventTypes = eventTypesCache.get(eventClass);
if (eventTypes == null) {
eventTypes = new ArrayList<>();
Class<?> clazz = eventClass;
while (clazz != null) {
eventTypes.add(clazz);
//添加发送事件类型的接口类
addInterfaces(eventTypes, clazz.getInterfaces());
//添加发送事件类型的父类,知道Object类则停止
clazz = clazz.getSuperclass();
}
//放到缓存中
eventTypesCache.put(eventClass, eventTypes);
}
return eventTypes;
}
}
这里先从缓存中获取事件类型列表,如果没有,则创建,然后添加当前事件类型、事件类型的接口类、事件类型的父类,最后再放到eventTypesCache->HashMap中。
发送事件类型(包括事件类型的父类和实现的接口类)举例
public interface Animal {
}
public class DogEvent {
}
public class MessageEvent extends DogEvent implements Animal {
private String name;
public MessageEvent(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
发送事件
mBtn1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
EventBus.getDefault().post(new MessageEvent("hao"));
}
});
订阅方法
@Subscribe(threadMode = ThreadMode.MAIN)
public void messageEvent(MessageEvent evet){
Log.d("message", "MessageEvent");
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void dogEvent(DogEvent evet){
Log.d("message", "DogEvent");
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void animal(Animal evet){
Log.d("message", "Animal");
}
打印结果
12-11 10:23:01.530 5509-5509/com.cn.liuyz.javademo D/message: MessageEvent
12-11 10:23:01.531 5509-5509/com.cn.liuyz.javademo D/message: Animal
12-11 10:23:01.531 5509-5509/com.cn.liuyz.javademo D/message: DogEvent
这里所说的发送事件类型的列表,就包括Animal、DogEvent、MessageEvent、Object,当只发送MessageEvent事件时,列表中这几个订阅事件都可以接受到。
postSingleEventForEventType方法
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) {
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;
}
subscriptionsByEventType中Key是订阅方法中事件类型的Class对象,value是存放Subscription的集合,在Subscription中保存着订阅者和订阅方法。
postToSubscription方法
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 {
//利用Handler机制,把信息发送到主线程,再通过反射调用订阅方法
mainThreadPoster.enqueue(subscription, event);
}
break;
case MAIN_ORDERED://主线程执行,非阻塞式
if (mainThreadPoster != null) {
mainThreadPoster.enqueue(subscription, event);
} else {
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:
}
}
先获取订阅方法运行的线程,再各个处理,如MAIN主线程,是则通过反射invoke调用订阅方法,否则利用Handler机制,把信息发送到主线程,再通过反射invoke调用订阅方法。
HandlerPoster、BackgroundPoster、AsyncPoster稍后再讲解…
BACKGROUND和ASYNC区别
BACKGROUND中的任务是一个接着一个去调用,使用executorRunning布尔值进行控制(顺序执行)
Async中的任务会立即获取空闲线程或者直接创建线程去执行(并发执行)
都是使用Executors.newCachedThreadPool()线程池
invokeSubscriber方法
void invokeSubscriber(Subscription subscription, Object event) {
try {
//通过反射调用订阅方法
subscription.subscriberMethod.method.invoke(subscription.subscriber, event);
}
.....省略.....
}
发送事件到此就结束了
总结
第一步:获取一个与当前线程相关联的PostingThreadState对象
第二步:把事件添加到PostingThreadState的事件列表中,再以循环的方式发送事件
第三步:利用反射的方式调用订阅者的订阅方法
unregister取消注册
public synchronized void unregister(Object subscriber) {
//获取订阅者的订阅事件类型集合
List<Class<?>> subscribedTypes = typesBySubscriber.get(subscriber);
if (subscribedTypes != null) {
for (Class<?> eventType : subscribedTypes) {
//遍历所有订阅事件,并移除此订阅者
unsubscribeByEventType(subscriber, eventType);
}
//移除订阅者
typesBySubscriber.remove(subscriber);
} else {
logger.log(Level.WARNING, "Subscriber to unregister was not registered before: " + subscriber.getClass());
}
}
unsubscribeByEventType方法
private void unsubscribeByEventType(Object subscriber, Class<?> eventType) {
//根据事件类型从subscriptionsByEventType中获取相应的 subscriptions 集合
List<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
if (subscriptions != null) {
int size = subscriptions.size();
//遍历订阅者集合,从subscriptions中移除订阅者
for (int i = 0; i < size; i++) {
Subscription subscription = subscriptions.get(i);
if (subscription.subscriber == subscriber) {
subscription.active = false;
subscriptions.remove(i);
i--;
size--;
}
}
}
}
总结
第一步:获取订阅者内的所有订阅事件的集合
第二步:根据订阅事件获取所有的订阅了该事件的订阅者集合,再从订阅者集合中移除当前订阅者
第三步:从typesBySubscriber中移除订阅者
粘性事件的发送及接收源码分析
粘性事件与一般的事件不同,粘性事件是先发送出去,然后让后面注册的订阅者能够收到该事件。粘性事件的发送是通过postSticky方法进行发送
发送粘性事件
EventBus.getDefault().postSticky(new MessageEvent(""));
订阅方法
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true, priority = 100)
public void sticky1(MessageEvent event) {
Log.d("message", "");
}
threadMode:订阅方法运行的线程
sticky:是否为粘性事件
priority:优先级,优先级越高,在调用时越先调用
postSticky方法
public void postSticky(Object event) {
synchronized (stickyEvents) {
stickyEvents.put(event.getClass(), event);
}
post(event);
}
先把事件放到stickyEvents->HashMap中
再调用post方法,就和正常发送一样了,但不会有相应的订阅者内的订阅方法来响应
注意
stickyEvents中Key是订阅事件的Class对象,如果在不同的类中发送的粘性事件对象相同,则会覆盖之前的,保存最后一次发送的粘性事件对象,如果在不同的类中发送的粘性事件对象不同,则不受影响,都可以接受到。
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
.....省略.....
//sticky从订阅方法的注解上获取
if (subscriberMethod.sticky) {
if (eventInheritance) {//默认true
//获取所有粘性事件
Set<Map.Entry<Class<?>, Object>> entries = stickyEvents.entrySet();
for (Map.Entry<Class<?>, Object> entry : entries) {
//获取Map中的key即订阅事件的Class对象
Class<?> candidateEventType = entry.getKey();
//如果订阅者订阅的事件类型与当前的粘性事件类型相同,则把该事件分发给这个订阅者
if (eventType.isAssignableFrom(candidateEventType)) {
//获取Map中的value即订阅事件类型对象
Object stickyEvent = entry.getValue();
//发送事件
checkPostStickyEventToSubscription(newSubscription, stickyEvent);
}
}
} else {
//根据eventType,从stickyEvents集合中获取指定的事件类型对象
Object stickyEvent = stickyEvents.get(eventType);
//发送事件
checkPostStickyEventToSubscription(newSubscription, stickyEvent);
}
}
}
checkPostStickyEventToSubscription方法
private void checkPostStickyEventToSubscription(Subscription newSubscription, Object stickyEvent) {
if (stickyEvent != null) {
//执行订阅方法
postToSubscription(newSubscription, stickyEvent, isMainThread());
}
}
Poster源码解析
HandlerPoster
构造方法
protected HandlerPoster(EventBus eventBus, Looper looper, int maxMillisInsideHandleMessage) {
super(looper);
this.eventBus = eventBus;
//在主线程运行处理消息的最大时间,默认是10毫秒
this.maxMillisInsideHandleMessage = maxMillisInsideHandleMessage;
//PendingPostQueue队列
queue = new PendingPostQueue();
}
enqueue方法
public void enqueue(Subscription subscription, Object event) {
//将Subscription和订阅事件封装到PendingPost中
PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
synchronized (this) {
//添加到队列中
queue.enqueue(pendingPost);
//如果handlerActive为true,说明正在处理消息,我们只需要加入队列即可
if (!handlerActive) {
handlerActive = true;
//发送消息
if (!sendMessage(obtainMessage())) {
throw new EventBusException("Could not send handler message");
}
}
}
}
handleMessage方法
public void handleMessage(Message msg) {
boolean rescheduled = false;
try {
long started = SystemClock.uptimeMillis();
while (true) {
//循环从队列中取出pendingPost
PendingPost pendingPost = queue.poll();
if (pendingPost == null) {
synchronized (this) {
//为null时,再次取一下
pendingPost = queue.poll();
if (pendingPost == null) {
//循环停止
handlerActive = false;
return;
}
}
}
//利用反射调用订阅方法
eventBus.invokeSubscriber(pendingPost);
//判断消息处理时间,大于10毫秒则抛异常
long timeInMethod = SystemClock.uptimeMillis() - started;
if (timeInMethod >= maxMillisInsideHandleMessage) {
if (!sendMessage(obtainMessage())) {
throw new EventBusException("Could not send handler message");
}
rescheduled = true;
return;
}
}
} finally {
handlerActive = rescheduled;
}
}
HandlerPoster的执行是顺序一个一个执行的
都注释的很清楚了,就不总结了。
BackgroundPoster
BackgroundPoster(EventBus eventBus) {
this.eventBus = eventBus;
//PendingPostQueue队列
queue = new PendingPostQueue();
}
public void enqueue(Subscription subscription, Object event) {
PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
synchronized (this) {
//添加到队列中
queue.enqueue(pendingPost);
//如果executorRunning为true,说明正在处理消息,我们只需要加入队列即可
if (!executorRunning) {
executorRunning = true;
//获取Executors.newCachedThreadPool()缓存线程池并执行(调用run方法)
eventBus.getExecutorService().execute(this);
}
}
}
public void run() {
try {
try {
while (true) {
//循环从队列中取出pendingPost,最大等待时间是10毫秒
PendingPost pendingPost = queue.poll(1000);
.....省略.....
eventBus.invokeSubscriber(pendingPost);
}
.....省略.....
}
}
}
BackgroundPoster的执行是顺序一个一个执行的
AsyncPoster
AsyncPoster(EventBus eventBus) {
this.eventBus = eventBus;
queue = new PendingPostQueue();
}
public void enqueue(Subscription subscription, Object event) {
PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
//添加到队列中
queue.enqueue(pendingPost);
//获取Executors.newCachedThreadPool()缓存线程池并执行(调用run方法);
eventBus.getExecutorService().execute(this);
}
这里是立即执行,如果有缓存线程则获取缓存线程调用run方法,如果没有缓存线程则创建线程调用run方法,AsyncPoster的执行是并发的
public void run() {
PendingPost pendingPost = queue.poll();
if(pendingPost == null) {
throw new IllegalStateException("No pending post available");
}
eventBus.invokeSubscriber(pendingPost);
}
其他方法
EventBus.getDefault().cancelEventDelivery(event) ;//优先级高的订阅者可以终止事件往下传递
EventBus.getDefault().isRegistered(this);//判断当前类是否注册了EventBus
EventBus.getDefault().removeAllStickyEvents();//删除所有粘性事件