EventBus
源码解析
EventBus
是一个性能高效的基于观察者模式的事件发布与订阅框架.借助EventBus
,我们只需几行代码便能实现组件之间、线程之间的通信
先说明一下
EventBus
中三个重要的角色:Publisher
、Event
、Subscriber
. Event
:事件,它可以是任意类型,EventBus
会根据事件的类型进行全局发送 Pushlisher
:事件的发布者,它可以在任意线程中发布事件。在使用时通常调用EventBus.getDefault()
方法获取一个EventBus
对象,再通过链 式编程调用post()
方法进行事件发送 SubScriber
:事件接收者 在EventBus3.0
之前,使用时必须以OnEvent
开头的几种接收方法来接收事件。这些方法分别为:onEvent
、 onEventMainThread
、onEventBackgroundThread
和onEventAsync
,但是在3.0之后处理方法可以自定义,但是要以注解@subscribe进行标示, 同时指定线程模型,线程模型默认为POSTING的方式。 Tips:本文分析的源码版本为EventBus:3.2.0
简单用法
在具体的进行源码分析前,我们回顾一下EventBus
的使用流程:
java
// 1.注册
EventBus.getDefault().register(this);
// 2.准备订阅方法
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(SayHelloEvent event) {
String message = event.getMessage();
...
}
// 3.发布事件
EventBus.getDefault().post(new SayHelloEvent("Hello,EventBus!!!"));
//4.反注册
EventBus.getDefault().unregister(this);
事件订阅发布的流程分析
我们就从用法入手,逐步分析EventBus
事件发布订阅的流程.
EventBus.getDefault()
创建EventBus
对象
在EventBus
使用的过程中,不管是注册、解注册或者是发送事件都会用到这个方法,所以我们首先看一下这个方法中都是做了什么。
java
public class EventBus{
/** Log tag, apps may override it. */
public static String TAG = "EventBus";
static volatile EventBus defaultInstance;
private static final EventBusBuilder DEFAULT_BUILDER = new EventBusBuilder();
private static final Map<Class<?>, List<Class<?>>> eventTypesCache = new HashMap<>();
private final Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType;
private final Map<Object, List<Class<?>>> typesBySubscriber;
private final Map<Class<?>, Object> stickyEvents;
private final ThreadLocal<PostingThreadState> currentPostingThreadState = new ThreadLocal<PostingThreadState>() {
@Override
protected PostingThreadState initialValue() {
return new PostingThreadState();
}
};
......
......
/** Convenience singleton for apps using a process-wide EventBus instance. */
// 单例,double check
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;
}
public EventBus() {
this(DEFAULT_BUILDER);
}
// eventBus的具体构建通过bulier模式完成
EventBus(EventBusBuilder builder) {
logger = builder.getLogger();
//这个集合可以根据事件类型获取订阅者
//key:事件类型class,value:CopyOnWriteArrayList<Subscription>订阅该事件的订阅者集合
subscriptionsByEventType = new HashMap<>();
//订阅者所订阅的事件集合
//key:订阅者,value:List<Class<?> 该订阅者订阅的事件类型集合
typesBySubscriber = new HashMap<>();
//粘性事件集合
//key:事件Class对象,value:事件对象
stickyEvents = new ConcurrentHashMap<>();
// 是否支持Android mainThread
mainThreadSupport = builder.getMainThreadSupport();
// Android mainThread 事件发送者
mainThreadPoster = mainThreadSupport != null ? mainThreadSupport.createPoster(this) : null;
// 后台线程事件发送者
backgroundPoster = new BackgroundPoster(this);
// 异步线程事件发送者
asyncPoster = new AsyncPoster(this);
indexCount = builder.subscriberInfoIndexes != null ? builder.subscriberInfoIndexes.size() :0;
// 订阅者订阅事件查找者
subscriberMethodFinder = new SubscriberMethodFinder(builder.subscriberInfoIndexes,
builder.strictMethodVerification, builder.ignoreGeneratedIndex);
......
......
// private final static ExecutorService DEFAULT_EXECUTOR_SERVICE = Executors.newCachedThreadPool();
executorService = builder.executorService;
}
}
EventBus
通过EventBusBuilder
来初始化EventBus
对象,通过单例模式对外公开这个实例. subscriptionsByEventType
、typesBySubScriber
、 stickEvents
、subcriberMethodFinder
几个属性比较重要,后续分析中会经常提到,先有个印象.
Tips: 我们可以通过
EventBusBuilder
来自定义配置一个EventBus
对象实例.
register(Object subscriber)
创建EventBus
对象之后需要将事件订阅者在EventBus
中进行注册。
JAVA
public void register(Object subscriber) {
Class<?> subscriberClass = subscriber.getClass();
// 解析subscriber类中@Subscribe标记的方法,返回一个List<SubscriberMethod>
List<SubscriberMethod> subscriberMethods =
subscriberMethodFinder.findSubscriberMethods(subscriberClass);
synchronized (this) {
// 遍历集合注册事件的subscriber;
for (SubscriberMethod subscriberMethod : subscriberMethods) {
subscribe(subscriber,subscriberMethod);
}
}
}
register()方法主要做了两件事情:
- 解析subscriber对象中被@Subscribe标记的方法
- 注册事件的Subscriber
subscriberMethodFinder.findSubscriberMethods(subscriberClass)
完成了@Subscribe标记方法的解析,此步骤的具体实现不影响我们 分析事件的发布流程(后面会分析具体流程),先看看解析返回的数据
@Subscribe
java
@Documented
@Retention(RetentionPolicy.RUNTIME) // @Subscribe注解在运行时依然存在
@Target({ElementType.METHOD})
public @interface Subscribe {
// 事件订阅执行时的线程类型;
ThreadMode threadMode() default ThreadMode.POSTING;
// 是否是粘性事件
boolean sticky() default false;
//事件被执行的优先级,优先级越高,越早执行
int priority() default 0;
}
SubscriberMethod.java
java
public class SubscriberMethod {
final Method method; // @Subscribe标记的方法的method
final ThreadMode threadMode; // 线程类型
final Class<?> eventType; // 方法参数的calss,事件的Class对象
final int priority; //优先级
final boolean sticky; //是否是粘性;
/** Used for efficient comparison */
String methodString;
public SubscriberMethod(Method method, Class<?> eventType, ThreadMode threadMode, int priority, boolean sticky) {
this.method = method;
this.threadMode = threadMode;
this.eventType = eventType;
this.priority = priority;
this.sticky = sticky;
}
...
...
}
List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass)
完成@Subscribe
注解解析,返回了解析结果 , SubscriberMethod
记录了@Subscribe标记的method
对象和@Subscribe
的值。接着注册事件的Subscriber。
java
// 遍历集合注册事件的subscriber;
for (SubscriberMethod subscriberMethod : subscriberMethods) {
subscribe(subscriber,subscriberMethod);
}
}
subscribe(Object subscriber, SubscriberMethod subscriberMethod)
java
// Must be called in synchronized block
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
//step1:
// 获取当前观察的事件类型
Class<?> eventType = subscriberMethod.eventType;
// 封装成一个Subscription对象
Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
//通过事件类型获取该事件的订阅者集合;
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);
}
}
int size = subscriptions.size();
// 按照priority的高低进行排序,将数据保存到EventBus的subscriptionsByEventType属性里面
for (int i = 0; i <= size; i++) {
if (i == size || subscriberMethod.priority > subscriptions.get(i).subscriberMethod.priority) {
subscriptions.add(i, newSubscription);
break;
}
}
//step2:
// 记录注册对象观察的事件类型,反注册时会用到;
List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);
if (subscribedEvents == null) {
subscribedEvents = new ArrayList<>();
typesBySubscriber.put(subscriber, subscribedEvents);
}
subscribedEvents.add(eventType);
// 方法被标记为接收stick,后面会分析stick事件
if (subscriberMethod.sticky) {
...
...
}
}
先看step1
干了什么?
subscriber
和 subscriberMethod
被包装成了Subscription
, 为啥不直接用SubscriberMethod
? 看看Subscription
里面有啥
Subscription.java
java
final class Subscription {
final Object subscriber; //@subscribe注解标记方法的持有对象
final SubscriberMethod subscriberMethod; //@Subscribe标记的方法解析后的数据
volatile boolean active;
Subscription(Object subscriber, SubscriberMethod subscriberMethod) {
this.subscriber = subscriber;
this.subscriberMethod = subscriberMethod;
active = true;
}
...
...
}
联想到Method的invoke()方法
java
// obj:方法的持有者的实例
// args:方法参数的实例
Object invoke(Object obj,Object...args)
obj
对应subscriber
, method
对象本身均保存在subscriberMethod
中,如果再获取args
,订阅方法执行的数据就都有了,接着看往下看:
java
Class<?> eventType = subscriberMethod.eventType;
// 封装成一个Subscription对象
Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
//获取该事件类型的Subscription集合,如果没有,就创建一个新的list放进去
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);
}
}
int size = subscriptions.size();
// 按照priority的高低进行排序,将Subscription数据保存进去
for (int i = 0; i <= size; i++) {
if (i == size || subscriberMethod.priority > subscriptions.get(i).subscriberMethod.priority) {
subscriptions.add(i, newSubscription);
break;
}
}
ok
, subscriptionsByEventType
里面保存了事件Class
--- List<Subscription>
的映射关系
画张图示意一下:
接着看step2
做了什么
java
//获取subscriber观测事件类型的集合
List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);
if (subscribedEvents == null) {
subscribedEvents = new ArrayList<>();
typesBySubscriber.put(subscriber, subscribedEvents);
}
subscribedEvents.add(eventType);
与上面一样,subscribedEvents
里面保存了订阅者subscriber
--- List<事件Class>
的集合映射
总结一下,register(Object subscriber)
执行完成后
subscriber
的注解数据保存到了EventBus
对象的subscriptionsByEventType
属性里面,通过Event的calss
, 可以获取对应的Subscription
,Subscription
里面保存了@Subscriber
标记的method
执行需要的数据subscriber
订阅的事件类型 保存到了EventBus
对象的subscribedEvents
里面 ,subscribedEvents
里面保存了subscriber
订阅的事件Class集合
post(Object event)
java
/** Posts the given event to the event bus. */
public void post(Object event) {
//因为可以在不同的线程中执行post方法,为了避免事件同步等操作,为不同的线程提供事件执行的环境
//ThreadLocal原理;
PostingThreadState postingState = currentPostingThreadState.get();
// 事件被触发前缓存到这里;
List<Object> eventQueue = postingState.eventQueue;
eventQueue.add(event);
if (!postingState.isPosting) {
postingState.isMainThread = isMainThread();
postingState.isPosting = true;
...
//触发事件
postSingleEvent(eventQueue.remove(0), postingState);
...
}
}
PostingThreadState
提供事件分发的执行环境,接着看postSingleEvent(eventQueue.remove(0), postingState)
java
private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {
Class<?> eventClass = event.getClass();
boolean subscriptionFound = false;
//事件是否支持继承结构?
//比如有两个Event a 和 Event b , a extends b
// 我们post event a ,由于a也可以看作一个b对象,所以也需要触发 event b;
if (eventInheritance) {
// 查找事件calss所有的superClass和interface,将其作为潜在的事件类型;
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);
}
if (!subscriptionFound) {
// post(new NoSubscriberEvent(this, event));
...
...
}
}
接着看postSingleEventForEventType(event, postingState, clazz);
java
private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class<?> eventClass) {
CopyOnWriteArrayList<Subscription> subscriptions;
synchronized (this) {
//通过subscriptionsByEventType获取事件的Subscribers;
subscriptions = subscriptionsByEventType.get(eventClass);
}
// 遍历执行订阅,由于register的时候根据priority排过顺序,proprity最大的会被先执行;
if (subscriptions != null && !subscriptions.isEmpty()) {
for (Subscription subscription : subscriptions) {
postingState.event = event;
postingState.subscription = subscription;
...
//触发Subscriber的onEvent
postToSubscription(subscription, event, postingState.isMainThread);
...
}
return true;
}
return false;
}
通过事件的class
找到事件的订阅者subscriptions
, 按照顺序依次执行订阅方法 , 说好的Eventbus
切换线程呢?,接着跟
java
private void postToSubscription(Subscription subscription, Object event,boolean isMainThread){
// 根据threadMode,切换不同的线程或直接执行
switch (subscription.subscriberMethod.threadMode) {
case POSTING:
// 直接执行订阅;
invokeSubscriber(subscription, event);
break;
case MAIN:
if (isMainThread) {
// 当前线程就是主线程,直接执行订阅;
invokeSubscriber(subscription, event);
}else{
//添加到mainThreadPoster的队列中去,在主线程中调用响应方法
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队列中等待被执行;
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);
}
}
// 通过反射的形式,执行对应方法,完成订阅;
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);
}
}
事件订阅执线程的切换分五种模式
-
POSTING
:当前线程直接执行 -
MAIN
: Android 主线程执行 -
MAIN_ORDERED
: 如果支持主线程执行那么让主线程执行,如果不支持主线程,直接在当前线程执行 -
BACKGROUND
: 如果在主线程,切换到后台线程执行,不是主线程,直接执行 -
ASYNC
:另开线程执行
Event是如何切换线程的
Event
切换线程执行是通过对应的Poster
来实现的,下面就具体分析一下不同类型的poster
Poster.java
java
// 定义了事件进入队列,事件的具体执行由其子类完成;
interface Poster {
/**
* Enqueue an event to be posted for a particular subscription.
*
* @param subscription Subscription which will receive the event.
* @param event Event that will be posted to subscribers.
*/
void enqueue(Subscription subscription, Object event);
}
Main
线程的HandlerPoster
mainThreadPoster
的实例是通过mainThreadSupport.createPoster(this)
来创建的,最终返回的是HandlderPoster
的一个实例
java
public class HandlerPoster extends Handler implements Poster{
private final PendingPostQueue queue;
private final int maxMillisInsideHandleMessage;
private final EventBus eventBus;
private boolean handlerActive;
protected HandlerPoster(EventBus eventBus, Looper looper, int maxMillisInsideHandleMessage) {
super(looper);
this.eventBus = eventBus;
this.maxMillisInsideHandleMessage = maxMillisInsideHandleMessage;
queue = new PendingPostQueue();
}
public void enqueue(Subscription subscription, Object event) {
// 包装一下订阅执行数据,PendingPost内部也使用享元模式;
PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
synchronized (this) {
//放入队列中;
queue.enqueue(pendingPost);
if (!handlerActive) {
handlerActive = true;
// 发送一个事件的执行命令
if (!sendMessage(obtainMessage())) {
throw new EventBusException("Could not send handler message");
}
}
}
}
@Override
public void handleMessage(Message msg) {
boolean rescheduled = false;
try{
long started = SystemClock.uptimeMillis();
while(true){
//从队列中取出数据;
PendingPost pendingPost = queue.poll();
if (pendingPost == null){
// Check again, this time in synchronized
synchronized (this){
pendingPost = queue.poll();
if (pendingPost == null){
handlerActive = false;
return;
}
}
// 切换到主线程执行;
eventBus.invokeSubscriber(pendingPost);
}
}
}finally{
handlerActive = rescheduled;
}
}
void invokeSubscriber(PendingPost pendingPost){
Object event = pendingPost.event;
Subscription subscription = pendingPost.subscription;
PendingPost.releasePendingPost(pendingPost);
if (subscription.active){
// 实际还是调用的invokeSubscriber
invokeSubscriber(subscription, event);
}
}
}
HandlerPoster
通过handdler
的原理,将事件执行切换到main线程。
ASYNC
额外开启异步线程 AsyncPoster.java
java
class AsyncPoster implements Runnable, Poster {
private final PendingPostQueue queue;
private final EventBus eventBus;
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);
// 执行run方法,开新的线程;
eventBus.getExecutorService().execute(this);
}
@Override
public void run() {
// 获取订阅数据;
PendingPost pendingPost = queue.poll();
if(pendingPost == null) {
throw new IllegalStateException("No pending post available");
}
// 事件具体执行位置,实现是在eventBus.getExecutorService()指定的线程
eventBus.invokeSubscriber(pendingPost);
}
}
asyncPoster
执行事件在eventBus.getExecutorService()
的线程池的线程里面,每次发布事件都会在新线程里面执行
JAVA
// EventBus的默认线程池,每次执行runnable都是新开线程;
private final static ExecutorService DEFAULT_EXECUTOR_SERVICE = Executors.newCachedThreadPool();
/*
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}*/
BACKGROUND 后台线程执行事件
java
final class BackgroundPoster implements Runnable, Poster{
private final PendingPostQueue queue;
private final EventBus eventBus;
private volatile boolean executorRunning;
BackgroundPoster(EventBus eventBus) {
this.eventBus = eventBus;
queue = new PendingPostQueue();
}
// 事件进入backgroundPoster后是按照顺序执行的,每一批执行事件都是在同一个线程里面,下一批次事件执行会开启一个新的线程;
public void enqueue(Subscription subscription, Object event){
// 数据包装;
PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
synchronized (this) {
// 数据入队列
queue.enqueue(pendingPost);
// 数据并不是马上放入线程里面等待执行,而是在当前批次里面依次执行;
// 每次执行时只开一条线程;
if (!executorRunning){
executorRunning = true;
eventBus.getExecutorService().execute(this);
}
}
}
@Override
public void run() {
try{
//循环,每次执行都是将队列里面的事件全部执行完后才退出线程;
while(true){
PendingPost pendingPost = queue.poll(1000);
if (pendingPost == null) {
synchronized (this) {
pendingPost = queue.poll();
if (pendingPost == null){
executorRunning = false;
return;
}
}
}
// 事件执行;
eventBus.invokeSubscriber(pendingPost);
}
}catch(){
eventBus.getLogger().log(Level.WARNING, Thread.currentThread().getName() + " was interruppted", e);
}finally{
executorRunning = false;
}
}
}
backgroundPoster
执行事件也是在eventBus.getExecutorService()
的线程池的线程里面,直到当前队列里面事件执行完成之前,不会开启新的 线程来执行事件,事件的执行过程是串联起来的.也可以理解为事件是分批次来执行的,不同批次会开不同的线程执行,同一批次里面的事件在同 一个线程里面按照串联顺序依次执行.
unregister(Object subscriber)
EventBus.getDefault()
返回的是一个单例对象,保存在subscriptionsByEventType
中的Subscribers
不使用时需要清除避免内存泄漏.
java
public synchronized void unregister(Object subscriber) {
// 获取订阅对象拥有的所有事件类型,register时保存过subscriber观察的事件种类;
List<Class<?>> subscribedTypes = typesBySubscriber.get(subscriber);
if (subscribedTypes != null) {
for (Class<?> eventType : subscribedTypes) {
// 注销每种事件类型对应的Subscription;
unsubscribeByEventType(subscriber, eventType);
}
typesBySubscriber.remove(subscriber);
} else {
...
}
}
// 注销每种事件类型对应的Subscription,防止内存泄漏;
private void unsubscribeByEventType(Object subscriber, Class<?> eventType){
List<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
if (subscriptions != null){
int size = subscriptions.size();
for (int i = 0; i < size; i++){
Subscription subscription = subscriptions.get(i);
if (subscription.subscriber == subscriber){
subscription.active = false;
subscriptions.remove(i);
i--;
size--;
}
}
}
}
OK , EventBus
的主体流程就到处结束了
补充
Stick事件
stick事件与一般事件的区别在于stick事件的执行时机
java
public void postSticky(Object event){
synchronized (stickyEvents){
// 将事件存入stickyEvents容器内
stickyEvents.put(event.getClass(), event);
}
// 此时只是当作普通事件被post;
post(event);
}
// 移除stickevnet;
public <T> T removeStickyEvent(Class<T> eventType){
synchronized (stickyEvents){
return eventType.cast(stickyEvents.remove(eventType));
}
}
stick事件是在register
时触发的,看一下register
方法内部的subscribe
方法:
java
subscribe(Object subscriber, SubscriberMethod subscriberMethod){
Class<?> eventType = subscriberMethod.eventType;
Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
......
......
if (subscriberMethod.sticky){
// 默认eventInheritance = true;
if (eventInheritance){
// 遍历stickEvents容器,postStick的stick事件会被存进去, key是事件的calss对象,value是event实例
Set<Map.Entry<Class<?>, Object>> entries = stickyEvents.entrySet();
for (Map.Entry<Class<?>, Object> entry : entries){
Class<?> candidateEventType = entry.getKey();
// a.isAssignableFrom(b),a为b的父类或者接口|a与b是同一个类或者接口;
if (eventType.isAssignableFrom(candidateEventType)){
Object stickyEvent = entry.getValue();
// 触发stickEvent,注意post的event对象是之前存储在stickyEvents中的对象;
checkPostStickyEventToSubscription(newSubscription,stickyEvent);
}
}
}else{
Object stickyEvent = stickyEvents.get(eventType);
checkPostStickyEventToSubscription(newSubscription, stickyEvent);
}
}
}
// 执行事件订阅,与上面post方法殊途同归
private void checkPostStickyEventToSubscription(Subscription newSubscription, Object stickyEvent){
if (stickyEvent != null) {
postToSubscription(newSubscription, stickyEvent, isMainThread());
}
}
@Subscribe注解的解析的过程
最后补充一下@Subscribe
的解析过程
SubscriberMethodFinder.java
java
class SubscriberMethodFinder{
private static final int BRIDGE = 0x40;
private static final int SYNTHETIC = 0x1000;
private static final int MODIFIERS_IGNORE = Modifier.ABSTRACT | Modifier.STATIC | BRIDGE | SYNTHETIC;
private static final Map<Class<?>, List<SubscriberMethod>> METHOD_CACHE = new ConcurrentHashMap<>();
private List<SubscriberInfoIndex> subscriberInfoIndexes;
private final boolean strictMethodVerification; // 是否开启严格验证
private final boolean ignoreGeneratedIndex;
private static final int POOL_SIZE = 4;
private static final FindState[] FIND_STATE_POOL = new FindState[POOL_SIZE];
SubscriberMethodFinder(List<SubscriberInfoIndex> subscriberInfoIndexes, boolean strictMethodVerification,
boolean ignoreGeneratedIndex){
this.subscriberInfoIndexes = subscriberInfoIndexes;
this.strictMethodVerification = strictMethodVerification; // 默认false;
this.ignoreGeneratedIndex = ignoreGeneratedIndex; // 默认false;
}
......
......
List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass){
// 有缓存,直接从缓存中拿
List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);
if (subscriberMethods != null) {
return subscriberMethods;
}
if (ignoreGeneratedIndex) {
// 通过反射来解析数据;
subscriberMethods = findUsingReflection(subscriberClass);
}else{
// 通过apt来获取解析数据;
subscriberMethods = findUsingInfo(subscriberClass);
}
// 如果一个subscribe注解方法都没有找到,throw exception(),是不是见过这个异常
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;
}
}
// 通过反射来解析@Subscribe,数据的解析实际上放到了FindState类里面处理
private List<SubscriberMethod> findUsingReflection(Class<?> subscriberClass) {
FindState findState = prepareFindState(); // 享元模式
findState.initForSubscriber(subscriberClass);
// 切换到父类class,这样父类calss里面的@subscribe注解的方法也可以解析到
while (findState.clazz != null) {
findUsingReflectionInSingleClass(findState);
findState.moveToSuperclass();
}
return getMethodsAndRelease(findState);
}
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();
}
// 解析@Subscribe注解的辅助类
static class FindState{
final List<SubscriberMethod> subscriberMethods = new ArrayList<>();
final Map<Class, Object> anyMethodByEventType = new HashMap<>();
final Map<String, Class> subscriberClassByMethodKey = new HashMap<>();
final StringBuilder methodKeyBuilder = new StringBuilder(128);
......
......
//把当前class设置为父类class,过滤系统层面calss,防止无限制的解析
void moveToSuperclass() {
if (skipSuperClasses) {
clazz = null;
} else {
clazz = clazz.getSuperclass();
String clazzName = clazz.getName();
/** Skip system classes, this just degrades performance. */
if (clazzName.startsWith("java.") || clazzName.startsWith("javax.") || clazzName.startsWith("android.")) {
clazz = null;
}
}
}
}
// 解析@Subscribe的核心方法,结果保存再FindState的一个List<SubscriberMethod>属性下面
private void findUsingReflectionInSingleClass(FindState findState){
Method[] methods;
try{
// 获取class自己声明的方法,包括private的方法;
methods = findState.clazz.getDeclaredMethods();
}catch(Throwable th){
try{
//获取class的publish方法,包括继承得来的方法;
methods = findState.clazz.getMethods();
}catch(LinkageError error){
......
throw new EventBusException(msg, error);
}
findState.skipSuperClasses = true;
}
for (Method method : methods){
int modifiers = method.getModifiers();
// 通过方法修饰符过滤一下,要public,非abstract,非static, 非synthetic,非bridge,bridge是啥我也不知道
if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0){
Class<?>[] parameterTypes = method.getParameterTypes();
// 再过滤一下,只能是参数只有一个的方法,eventbus不支持参数 > 1
if (parameterTypes.length == 1){
// 获取@Subscribe注解对象;
Subscribe subscribeAnnotation = method.getAnnotation(Subscribe.class);
//有@subscribe,目标命中
if (subscribeAnnotation != null){
// 该方法只有一个事件对象作为参数,获取事件对象类型;
Class<?> eventType = parameterTypes[0];
//防止重写父类中的方法造成重复添加;
if (findState.checkAdd(method, eventType)){
ThreadMode threadMode = subscribeAnnotation.threadMode();
// 将@Subscribe注解的解析结果保存到SubscriberMethod对象中;
findState.subscriberMethods.add(new SubscriberMethod(method, eventType, threadMode,
subscribeAnnotation.priority(), subscribeAnnotation.sticky()));
}
}
}else if(strictMethodVerification && method.isAnnotationPresent(Subscribe.class)){
// 开启严格校验模式下,@Subscribe标记的方法的参数个数不为1会抛异常;
......
......
throw new EventBusException("@Subscribe method " + methodName +
"must have exactly 1 parameter but has " + parameterTypes.length);
}
}else if(strictMethodVerification && method.isAnnotationPresent(Subscribe.class)){
// 如果开启了严格校验,@Subscribe标记的方法的修饰符不满足要求会抛异常
......
throw new EventBusException(methodName +" is a illegal @Subscribe method: must be public, non-static, and non- abstract");
}
}
}
}