上一篇文章ButterKnife源码分析
EventBus适用于Android和Java的事件总线,简化了活动,碎片,线程,服务等之间的通信。减少代码,提高质量。EventBus主要用了观察者模式(也叫发布订阅者模式)实现代码之间的解耦。EventBus中提供异步的方式解决一个被观察者,多个被观察者,执行效率慢的问题。本文以3.1.1的源码为例。
EventBus的使用步骤和主要变量
使用的三步骤
//1 定义消息事件
public class MessageEvent { /* Additional fields if needed */ }
//2
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(MessageEvent event) {/* Do something */};
@Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
@Override
public void onStop() {
super.onStop();
EventBus.getDefault().unregister(this);
}
//3
EventBus.getDefault().post(new MessageEvent());
ThreadMode:每个订阅方法都有一个线程模式,该模式决定EventBus将在哪个线程中调用该方法。
- POSTING:那个线程发布事件,订阅者就在那个线程被调用;避免线程切换;不能做耗时操作,避免在主线程发布事件,阻塞主线程;
- MAIN:在Android中订阅者将在主线程中被调用,1)如果在主线程中发布事件,就立即调用订阅者;2)不是在主线程中发布事件,将事件放入队列中依次发布。如果不是在Android中,MAIN和POSTING一样;
- MAIN_ORDERED:在Android中,订阅者将在主线程中调用,和MAIN不同的是,事件加入队列依次发布,确保post不被阻塞;
- BACKGROUND:在Android中,订阅者将在后台线程中调用。1)如果不在主线程不发布事件,订阅者就直接在当前线程调用;2)如果在主线程中发布事件,EventBus在同一个后台线程中将事件加入队列依次发布;
- ASYNC:异步,订阅者在单独的线程中执行,可以执行耗时操作;EventBus使用线程池复用完成异步操作的线程;
EventBus的主要成员变量;
//key:事件的class,value:当前事件类的class,其实现的interface的class和其父类的class的集合;
private static final Map<Class<?>, List<Class<?>>> eventTypesCache = new HashMap<>();
//key:事件的class,value:事件的订阅者集合
private final Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType;
//key:订阅者,value:事件的集合;(一个订阅者多种不同的事件处理方法)
private final Map<Object, List<Class<?>>> typesBySubscriber;
//key:事件的class,value:事件对象;
private final Map<Class<?>, Object> stickyEvents;
//ThreadLocal每个线程的独有内存空间;线程安全,用空间换效率;常用在Handler中;不同线程发布的事件放入
//不同线程的threadLocal中,PostingThreadState中的eventQueue保存该线程发布的事件;
private final ThreadLocal<PostingThreadState> currentPostingThreadState = new ThreadLocal<PostingThreadState>() {
@Override
protected PostingThreadState initialValue() {
return new PostingThreadState();
}
};
EventBus的参数初始化;Poster的实现类在具体发布事件的时候,再细说;
EventBus(EventBusBuilder builder) {
//在Android中mainThreadSupport不为null;不在Android中为null;
mainThreadSupport = builder.getMainThreadSupport();
//在Android中mainThreadPoster为HandlePoster实例;否则为null;
mainThreadPoster = mainThreadSupport != null ? mainThreadSupport.createPoster(this) : null;
backgroundPoster = new BackgroundPoster(this);
asyncPoster = new AsyncPoster(this);
//cache线程池,最大线程数为Interger.MAX_VALUE;
executorService = builder.executorService;
}
getMainThreadSupport():创建AndroidHandlerMainThreadSupport的对象;
MainThreadSupport getMainThreadSupport() {
//默认情况下为null;
if (mainThreadSupport != null) {
return mainThreadSupport;
} else if (Logger.AndroidLogger.isAndroidLogAvailable()) {
//调用Looper.getMainLooper(),获取mainLooper;
Object looperOrNull = getAndroidMainLooperOrNull();
return looperOrNull == null ? null :
new MainThreadSupport.AndroidHandlerMainThreadSupport((Looper) looperOrNull);
} else {
return null;
}
}
register的过程
先从register()方法开始,一旦订阅者注册接受事件,就必须通过unRegister()才不再接受事件;注册的过程中做了很多的处理,我们慢慢道来;
订阅者还必须有@Subscribe()注解的事件处理方法,可以通过threadMode,sticky,priority来配置;threadMode:决定EventBus在那个线程调用事件处理方法,默认是POSTING;sticky:是否是粘性事件,默认为false;priority:影响发布事件的顺序,默认值为0;
public void register(Object subscriber) {
Class<?> subscriberClass = subscriber.getClass();
//找到订阅者类中定义的处理事件的方法(被@subscribe注解的方法);
List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
synchronized (this) {
for (SubscriberMethod subscriberMethod : subscriberMethods) {
subscribe(subscriber, subscriberMethod);
}
}
}
findSubscriberMethods()找到被@Subscribe注解的方法(接受事件的方法);
List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);
if (subscriberMethods != null) {
return subscriberMethods;
}
//默认为false
if (ignoreGeneratedIndex) {
subscriberMethods = findUsingReflection(subscriberClass);
} else {
subscriberMethods = findUsingInfo(subscriberClass);
}
//如果订阅者类中没有定义被@subscribe注解的方法,报错;
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():通过遍历找到订阅者或者其父类中的所有处理事件的方法;主要调用findUsingReflectionInSingleClass();
private List<SubscriberMethod> findUsingInfo(Class<?> subscriberClass) {
FindState findState = prepareFindState();
//初始化后,clazz为subscriberClass;subscriberInfo为null;
findState.initForSubscriber(subscriberClass);
while (findState.clazz != null) {
findState.subscriberInfo = getSubscriberInfo(findState);
//默认为null
if (findState.subscriberInfo != null) {
} else {
findUsingReflectionInSingleClass(findState);
}
//找到父类的clazz;
findState.moveToSuperclass();
}
return getMethodsAndRelease(findState);
}
findUsingReflectionInSingleClass():通过反射获取订阅者类中的所有方法,并遍历,找到对应的处理事件的方法(被@subscribe注解,是public的,不能被static,abstract修饰,并且只有一个参数),平时使用过程中,出现的异常信息,都可以在这个方法中找到。
private void findUsingReflectionInSingleClass(FindState findState) {
//通过反射获取订阅者的所有方法;
Method[] methods;
try {
methods = findState.clazz.getDeclaredMethods();
} catch (Throwable th) {
methods = findState.clazz.getMethods();
findState.skipSuperClasses = true;
}
//遍历方法,找到对应的处理事件的方法,并判断该方法是否符合要求;
for (Method method : methods) {
int modifiers = method.getModifiers();
//判断修饰符
if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) {
//方法是否只有一个参数;
Class<?>[] parameterTypes = method.getParameterTypes();
if (parameterTypes.length == 1) {
//是否被@subscribe注解;
Subscribe subscribeAnnotation = method.getAnnotation(Subscribe.class);
if (subscribeAnnotation != null) {
Class<?> eventType = parameterTypes[0];
if (findState.checkAdd(method, eventType)) {
//满足条件的方法添加到集合中;
ThreadMode threadMode = subscribeAnnotation.threadMode();
findState.subscriberMethods.add(new SubscriberMethod(method, eventType, threadMode,
subscribeAnnotation.priority(), subscribeAnnotation.sticky()));
}
}
}
}
}
}
subscribe():将订阅者和事件关联起来,同时为事件的优先级给订阅者排序;最后如果事件是粘性的,会把之前缓存的事件再次发布个接受者
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
//事件的class;
Class<?> eventType = subscriberMethod.eventType;
Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
//找到当前事件的已有订阅者集合,为null,就创建;将当前订阅者加入集合中;
CopyOnWriteArrayList<Subscription> 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);
}
}
//按优先级(priority)将订阅者排序,靠前的将优先执行;
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<>();
typesBySubscriber.put(subscriber, subscribedEvents);
}
subscribedEvents.add(eventType);
//粘性事件,依然会将之前的粘性事件再次发布给订阅者;这就是粘性事件和普通事件的最大的区别;
if (subscriberMethod.sticky) {
//默认为true,
if (eventInheritance) {
Set<Map.Entry<Class<?>, Object>> entries = stickyEvents.entrySet();
for (Map.Entry<Class<?>, 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);
}
}
}
到此注册的过程就完成了,接下来看事件的发布过程,相对来说,比较简单些;
事件发布过程
事件的发布通常分为两种方式:发布普通事件和发布粘性事件;
1)发布普通事件
post():将当前事件发送到所在线程的ThreadLocal中的List中,按顺序将事件发送出去;
public void post(Object event) {
PostingThreadState postingState = currentPostingThreadState.get();
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;
}
}
}
isMainThread():不是在Android中,mainThreadSupport为null,返回true;在Android中,发布事件是否在主线程中,在主线程中,为true,否者为false;
private boolean isMainThread() {
return mainThreadSupport != null ? mainThreadSupport.isMainThread() : true;
}
postSingleEvent():获取当前事件class对象、其的父类的class对象和其接口的class对象,遍历,发布事件;
private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {
Class<?> eventClass = event.getClass();
boolean subscriptionFound = false;
//默认为true;
if (eventInheritance) {
//将event类及其实现的接口和其父类存入List中;
List<Class<?>> eventTypes = lookupAllEventTypes(eventClass);
int countTypes = eventTypes.size();
for (int h = 0; h < countTypes; h++) {
Class<?> clazz = eventTypes.get(h);
//发布事件;如果postSingleEventForEventType()返回true,subscriptionFound就为true;
subscriptionFound |= postSingleEventForEventType(event, postingState, clazz);
}
} else {
subscriptionFound = postSingleEventForEventType(event, postingState, eventClass);
}
}
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;
}
2)发布粘性事件,除了要保存在stickyEvents中,其他的和发布普通的事件一样;
public void postSticky(Object event) {
synchronized (stickyEvents) {
//将当前粘性事件保存下来;订阅者可以通过getStickyEvent()获取到;
stickyEvents.put(event.getClass(), event);
}
// Should be posted after it is putted, in case the subscriber wants to remove immediately
post(event);
}
postToSubscription():是发布事件的核心方法;根据不同的threadMode参数和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);
}
break;
case MAIN_ORDERED:
//Android环境中mainThreadPoster不为null;
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:
throw new IllegalStateException("Unknown thread mode: " + subscription.subscriberMethod.threadMode);
}
}
Poster接口的具体实现类;
- HandlePoster类:是Handler的子类,其Looper为mainLooper;handleMessage()方法中有个死循环,不断的从PendingPostQueue队列中取出事件发布;订阅者方法在主线程中调用,不能做耗时操作;
- BackgroundPoster类:是个Runnable,run()方法中有个死循环,不断的发布事件;用线程池去执行BackgroundPoster,但是同一时间内最多只有一个runnable在执行;也就是说单独用一个线程不断的发布事件;
- AsyncPoster类:也是一个Runnable,每当有消息加入,就用线程池去执行,完全异步;
PendingPostQueue:就是一个先进先出的队列,以单链表来实现的,线程安全;
Poster的具体实现类和PendingPostQueue可自行详细的看一下;
不管是那种方式发布事件,最终都会调用invokeSubscriber(),通过反射调用处理事件的方法;
void invokeSubscriber(Subscription subscription, Object event) {
try {
subscription.subscriberMethod.method.invoke(subscription.subscriber, event);
} catch (InvocationTargetException e) {
handleSubscriberException(subscription, event, e.getCause());
} catch (IllegalAccessException e) {
throw new IllegalStateException("Unexpected exception", e);
}
}
unregister()方法
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);
}
}
EventBusAnnotationProcessor类
EventBusAnnotationProcessor类主要是在编译阶段,生成对应的信息检索文件。
//支持的注解类型,Subscribe注解;
@SupportedAnnotationTypes("org.greenrobot.eventbus.Subscribe")
@SupportedOptions(value = {"eventBusIndex", "verbose"})
public class EventBusAnnotationProcessor extends AbstractProcessor {
//annotations为支持的注解的集合;
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment env) {
Messager messager = processingEnv.getMessager();
String index = processingEnv.getOptions().get(OPTION_EVENT_BUS_INDEX);
//需要在项目的gradle中配置;
if (index == null) {
messager.printMessage(Diagnostic.Kind.ERROR, "No option " + OPTION_EVENT_BUS_INDEX +
" passed to annotation processor");
return false;
}
verbose = Boolean.parseBoolean(processingEnv.getOptions().get(OPTION_VERBOSE));
int lastPeriod = index.lastIndexOf('.');
String indexPackage = lastPeriod != -1 ? index.substring(0, lastPeriod) : null;
//遍历支持的注解的集合,找到被注解的方法,判断是否符合规则;
//如:是否为public的,不能被static修饰等,必须有一个参数;满足条件的放入methodsByClass中;
collectSubscribers(annotations, env, messager);
checkForSubscribersToSkip(messager, indexPackage);
//如果有订阅者处理事件的方法,生成信息检索文件;
if (!methodsByClass.isEmpty()) {
createInfoIndexFile(index);
}
return true;
}
index的值需要在项目的gradle中配置;如EventBusPerformance的build.gradle;生成的检索信息在build/generated/source/apt/debug/包名/目录下,类名为MyEventBusIndex的java文件;
defaultConfig {
javaCompileOptions {
annotationProcessorOptions {
arguments = [eventBusIndex: 'org.greenrobot.eventbusperf.MyEventBusIndex']
}
}
}
以上就是EventBus源码分析的主要内容,如有问题,请多指教,谢谢!