final class Subscription {
final Object subscriber; // Object对象,反射invoke方法时传入
final SubscriberMethod subscriberMethod; // 一个使用Subscribe注解标记的方法
}
SubscriberMethod.java
是一个bean类型的方法。
注解方法解析后的封装对象。封装了一个使用 Subscribe注解的方法。可以用来处理消息。
final Method method; //经过注册解析得到的函数方法,用于处理post的事件。
final ThreadMode threadMode; // 线程模式
final Class<?> eventType; // event 事件类型。注解方法的入参类型,post函数的入参类型
final int priority; // 优先级,优先级越高,越先收到消息通知。
final boolean sticky; // 是否支持粘性方法。
PendingPost.java
Post事件对象,采用了对象池。
PendingPostQueue.java
链表实现的一个简单的事件队列
注解相关
@Subscribe注解
Subscribe注解 表示一个方法注册监听消息事件
ThreadMode
POSTING 默认模式。直接在本线程调用执行其他对象注册的函数方法。
MAIN APP主函数调用,应该避免阻塞操作。如果当前线程是主函数,那么会直接调用。如果不是主线程,那么会先通过handler抛到主函数的事件队列中处理。
ASYNC 所有消息都会抛到一个独立的线程处理。适合耗时操作。执行线程从线程池中获取。EventBus会采用线程池,动态的扩展线程。默认采用的线程池是newCachedThreadPool. 避免同时提交过多的耗时操作,导致线程池创建过多的线程。 Avoid triggering a large number of long running asynchronous subscriber methods at the same time to limit the number of concurrent threads
org.greenrobot.eventbus.EventBusBuilder
private final static ExecutorService DEFAULT_EXECUTOR_SERVICE = Executors.newCachedThreadPool();
/**
* Each subscriber method has a thread mode, which determines in which thread the method is to be called by EventBus.
* EventBus takes care of threading independently from the posting thread.
*
* @see EventBus#register(Object)
* @author Markus
*/
public enum ThreadMode {
/**
* Subscriber will be called directly in the same thread, which is posting the event. This is the default. Event delivery
* implies the least overhead because it avoids thread switching completely. Thus this is the recommended mode for
* simple tasks that are known to complete in a very short time without requiring the main thread. Event handlers
* using this mode must return quickly to avoid blocking the posting thread, which may be the main thread.
*/
POSTING,
/**
* On Android, subscriber will be called in Android's main thread (UI thread). If the posting thread is
* the main thread, subscriber methods will be called directly, blocking the posting thread. Otherwise the event
* is queued for delivery (non-blocking). Subscribers using this mode must return quickly to avoid blocking the main thread.
* If not on Android, behaves the same as {@link #POSTING}.
*/
MAIN,
/**
* On Android, subscriber will be called in Android's main thread (UI thread). Different from {@link #MAIN},
* the event will always be queued for delivery. This ensures that the post call is non-blocking.
*/
MAIN_ORDERED,
/**
* On Android, subscriber will be called in a background thread. If posting thread is not the main thread, subscriber methods
* will be called directly in the posting thread. If the posting thread is the main thread, EventBus uses a single
* background thread, that will deliver all its events sequentially. Subscribers using this mode should try to
* return quickly to avoid blocking the background thread. If not on Android, always uses a background thread.
*/
BACKGROUND,
/**
* Subscriber will be called in a separate thread. This is always independent from the posting thread and the
* main thread. Posting events never wait for subscriber methods using this mode. Subscriber methods should
* use this mode if their execution might take some time, e.g. for network access. Avoid triggering a large number
* of long running asynchronous subscriber methods at the same time to limit the number of concurrent threads. EventBus
* uses a thread pool to efficiently reuse threads from completed asynchronous subscriber notifications.
*/
ASYNC
}
/**
* Registers the given subscriber to receive events. Subscribers must call {@link #unregister(Object)} once they
* are no longer interested in receiving events.
* <p/>
* Subscribers have event handling methods that must be annotated by {@link Subscribe}.
* The {@link Subscribe} annotation also allows configuration like {@link
* ThreadMode} and priority.
*/
public void register(Object subscriber) {
Class<?> subscriberClass = subscriber.getClass();
// 解析类的所有方法,找到有注解的方法
List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
synchronized (this) {
for (SubscriberMethod subscriberMethod : subscriberMethods) {
subscribe(subscriber, subscriberMethod); //将解析的方法,添加到map数据结构中去
}
}
}
findSubscriberMethods,解析@Subscribe解方法
入参是register注册函数传入的subscriber的class对象类型。
如果找不到注解函数,会抛出异常。
List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass); //查缓存
if (subscriberMethods != null) {
return subscriberMethods;
}
if (ignoreGeneratedIndex) { // 是否忽略通过预编译生成的Index查找Method额方式,默认值false
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;
}
}
// 根据不同的threadMode,通过不同的线程进行处理
// 可以参考对ThreadMode的注解
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:
if (mainThreadPoster != null) { // Android场景下,这个变量一直非空
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); //如果在主线程,需要切换后台线程执行
} else {
invokeSubscriber(subscription, event); //如果当前在后台,直接调用方法
}
break;
case ASYNC:
asyncPoster.enqueue(subscription, event); // 所有事件,异步执行
break;
default:
throw new IllegalStateException("Unknown thread mode: " + subscription.subscriberMethod.threadMode);
}
}
/**
* Invokes the subscriber if the subscriptions is still active. Skipping subscriptions prevents race conditions
* between {@link #unregister(Object)} and event delivery. Otherwise the event might be delivered after the
* subscriber unregistered. This is particularly important for main thread delivery and registrations bound to the
* live cycle of an Activity or Fragment.
*/
void invokeSubscriber(PendingPost pendingPost) {
Object event = pendingPost.event;
Subscription subscription = pendingPost.subscription;
PendingPost.releasePendingPost(pendingPost);
if (subscription.active) {
invokeSubscriber(subscription, event);
}
}
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);
}
}
// Build the project at least once to generate the index class specified with eventBusIndex.
// Then, e.g. in your Application class, use EventBus.builder().addIndex(indexInstance) to pass an instance of the index class to EventBus.
EventBus eventBus = EventBus.builder().addIndex(new MyEventBusIndex()).build();
// Use EventBusBuilder.installDefaultEventBus() to set the EventBus with index as the instance returned by EventBus.getDefault().
EventBus.builder().addIndex(new MyEventBusIndex()).installDefaultEventBus();
// Now the default instance uses the given index. Use it like this:
EventBus eventBus = EventBus.getDefault();