Android框架-EventBus

转载
EventBus 结构

结构说明
Map<Class<?>, CopyOnWriteArrayList> subscriptionsByEventType
根据事件类型归类
key:事件类型
value:订阅该事件的 订阅者、回调方法
收到一个事件时,根据事件类型,
快速找到所有订阅者、及订阅者的回调方法
Map<Object, List<Class<?>>> typesBySubscriber
根据订阅者归类
key:订阅者
value:每个订阅者 所监听的 事件类型表
取消注册时可以通过该表中保存的信息
快速删除 订阅者的注册信息,避免遍历查找
MainThreadSupport用于创建
mainThreadPoster = new HandlerPoster(eventBus, looper, 10);
HandlerPoster 是一个绑定了主线程的 Handler
Poster mainThreadPoster控制回调函数在主线程中调用
利用 Handler 的消息队列存放事件
BackgroundPoster backgroundPoster控制回调函数在后台线程(线程池)调用
用一个 单链表 存放事件
AsyncPoster asyncPoster控制回调函数在线程池调用
用一个 单链表 存放事件
ExecutorService executorService用于执行 BACKGROUND / ASYNC 类型事件回调的线程池
core = 0
maxSize = Integer.MAX_VALUE
keepAlive = 60 秒
Map<Class<?>, List<Class<?>>> eventTypesCachekey:EventClass
value:该Class实现的接口
会循环遍历获取 EventClass 的父类,及父类实现的接口
Map<Class<?>, Object> stickyEvents粘性事件存储容器
key:EventClass 事件类型
value:粘性事件列表
粘性事件:EventBus # postSticky(event) 发送
1、粘性事件发送时会把 [EventClass, event] 的方式存入 stickyEvents
下次注册订阅者时,发现有粘性事件,直接从缓存获取事件、发送
2、postSticky(event) 发送同类型的粘性事件,会覆盖之前该类型的粘性事件
stickEvents 的 key 是事件类 Class
相同 Class 的粘性事件只会存一份,新的覆盖旧的

三个 Poster

Poster说明
ThreadMode # POSTING 调用 post 所在的线程执行回调,不需要 poster 来调度,直接运行
ThreadMode # MAIN在UI线程回调,如果 post 所在线程为UI 线程则直接运行,否则通过 mainThreadPoster 调度
ThreadMode # MAIN_ORDERED在UI线程回调,该模式下,事件会塞到队列中等待执行,不会阻塞主线程
ThreadMode # BACKGROUND在 Background 线程回调
如果post所在线程非UI线程,则直接执行,否则通过 backgroundPoster调度
ThreadMode # ASYNC交给线程池来管理,直接通过 asyncPoster调度
ASYNC 与 BACKGROUND 的区别BACKGROUND 的事件,在子线程发送,则直接调用回掉函数,不会用线程池回调
ASYNC的事件,直接用线程池来执行回调函数

EventBus 执行过程

如果是粘性事件
EventBus # getDefault 创建实例
EventBus # register 注册订阅者
传入订阅者对象
subscribe
根据 订阅者 Class 获取 Subscribe 注解的 回调函数
把每个回调方法和订阅者一起封装成 Subscription
存入 subscriptionsByEventType 和 typesBySubscriber
根据 EventClass 从 stickyEvents 中获取事件 发送
postToSubscription
根据 回调函数的 ThreadMode 使用不同的 poster
在对应线程中 通过反射 invoke 调用回调函数
EventBus # post
EventBus # postSticky 发送粘性事件
事件存入 stickEvents 缓存
key 为 EventClass
value 为 event
通过 threadLocal 获取当前线程的 PostingThreadState 对象
把事件放入 当前线程的 postingState # eventQueue 中 与 post 线程绑定
循环从 eventQueue 中取出事件
获取事件的所有父类
如果父类也是一种事件类型 则父类类型事件也会被发射
subscriptionsByEventType 获取 该事件类型的 所有 订阅者 及 回调方法
EventBus # unregister
typesBySubscriber 中取出 订阅者的所有事件类型
遍历所有事件
subscriptionsByEventType
相应事件的相应队列中删掉该订阅者
typesBySubscriber 中删除订阅者的事件列表

索引加速

编译时 EventBus注解处理器
处理 Subscribe 注解
生成索引类 MyEventBusIndex
索引类中用 HashMap保存 订阅者和回调函数信息
key-订阅者的类
value-SimpleSubscriberInfo
索引类在编译时生成
在索引类加载时把订阅者及回调函数存入缓存
避免在 EventBus # register 时才去遍历查找生成
把在注册时需要遍历订阅者所有方法的行为
提前到在编译时完成
通过 EventBusBuilder # addIndex 添加索引类
添加索引后
EventBus # register 注册时 从索引缓存中读取订阅者

注意事项
1)混淆问题

-keep public enum org.greenrobot.eventbus.ThreadMode { public static *; }

//keep住所有被 @Subscribe 标注的方法
-keepclassmembers class * {
	@de.greenrobot.event.Subscribe <methods>;
}

2)不支持跨进程

3)避免出现事件环路问题
比如,
订阅者A 接收到 事件B 后,发送 事件A
订阅者B 接收到 事件A 后,发送 事件B
导致死循环。

4)复杂的事件功能,可以考虑使用 RxBus

============= 下面是源码分析,可看可不看 ==============

核心架构

基于 观察者模式 的事件发布/订阅框架。

public class EventBus {

	/* key为事件类型,value为订阅者的回调方法
	 * EventBus在收到一个事件时,就可以根据这个事件的类型,
	 * 在 subscriptionsByEventType 中找到所有监听了该事件的订阅者及处理事件的回调方法。
	 */
	private final Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType;
	
	/* 每个订阅者所监听的事件类型表
	* 取消注册时可以通过该表中保存的信息,
	* 快速删除 subscriptionByEventType 中订阅者的注册信息,避免遍历查找。
	*/
	private final Map<Object, List<Class<?>>> typesBySubscriber;
	
	private final Map<Class<?>, Object> stickyEvents;

	//用于获取当前线程的 PostingThreadState 对象
	private final ThreadLocal<PostingThreadState> currentPostingThreadState = new ThreadLocal<PostingThreadState>() {
		@Override
		protected PostingThreadState initialValue() {
			return new PostingThreadState();
		}
	};

	/* 用于创建 mainThreadPoster = new HandlerPoster(eventBus, looper, 10);
	 * HandlerPoster 是一个绑定了主线程的 Handler
	 */
	private final MainThreadSupport mainThreadSupport;
	
	//控制回调函数在主线程中调用
	private final Poster mainThreadPoster;
	//控制回调函数在后台线程(线程池)调用
	private final BackgroundPoster backgroundPoster;
	//控制回调函数在线程池调用
	private final AsyncPoster asyncPoster;
	
	private final SubscriberMethodFinder subscriberMethodFinder;
	
	//用于执行 BACKGROUND/ASYNC 类型事件回调的线程池
	private final ExecutorService executorService;
	/*key:EventClass,value:该Class实现的接口
	* 会循环遍历获取 EventClass的父类,及父类实现的接口
	*/
	private static final Map<Class<?>, List<Class<?>>> eventTypesCache = new HashMap<>();
}
1、Map<Class<?>, CopyOnWriteArrayList> subscriptionsByEventType

key为事件类型,value为订阅者的回调方法
EventBus 在收到一个事件时,就可以根据这个事件的类型,
在 subscriptionsByEventType 中找到所有监听了该事件的订阅者及处理事件的回调方法。

2、Map<Object, List<Class<?>>> typesBySubscriber

每个订阅者 (比如一个Activity可以当作一个订阅者) 所监听的事件类型表
取消注册时可以通过该表中保存的信息,
快速删除 subscriptionByEventType 中订阅者的注册信息,避免遍历查找。

3、回调方法

回调方法,在这里被封装成了 SubscriptionMethod
里面保存了各种参数,包括优先级、是否接收黏性事件、所在线程等。

在 register() 时,会根据注解得到订阅者的所有回调方法、以及方法回调线程、优先级等信息
封装成 SubscriptionMethod 返回给 EventBus

4、三个Poster
public enum ThreadMode {
	//在调用post所在的线程执行回调,不需要 poster 来调度,直接运行。
	POSTING,
	
	//在UI线程回调,如果post 所在线程为UI 线程则直接运行,否则通过 mainThreadPoster 调度
	MAIN,

	//在UI线程回调,该模式下,事件会塞到队列中等待执行,不会阻塞主线程
	MAIN_ORDERED,

	/* 在 Background 线程回调。
	* 如果post所在线程非UI线程,则直接执行,否则通过backgroundPoster调度
	*/
	BACKGROUND,

	//交给线程池来管理,直接通过asyncPoster调度
	ASYNC
}

ASYNC 与 BACKGROUND的区别:
BACKGROUND的事件,如果是在子线程发送,则直接调用回掉函数,不会用线程池回调。
ASYNC的事件,如果直接用线程池来执行回调函数。

1)Poster mainThreadPoster:用于调度事件在主线程回调
由 MainThreadSupport 创建,是一个绑定了主线程的 Handler对象 HandlerPoster。

public class HandlerPoster extends Handler implements Poster {
	
	private final EventBus eventBus;
	
	/* PendingPostQueue 中维护了一个单链表,用于存储需要在主线程回调的事件
	* 链表元素为 PendingPost
	*/
	private final PendingPostQueue queue;
	...
	public void enqueue(Subscription subscription, Object event) {
		//把事件构造成一个 PendingPost 对象
		PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
		synchronized (this) {
			//PendingPost 对象 塞入队列
			queue.enqueue(pendingPost);
			if (!handlerActive) {
				handlerActive = true;
				/* 调用Handler.sendMessage发送事件
				* 由于该 Handler 与主线程绑定,消息会回调到主线程处理
				*/
				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) {
					synchronized (this) {
						// Check again, this time in synchronized
						pendingPost = queue.poll();
						if (pendingPost == null) {
							handlerActive = false;
							return;
						}
					}
				}
				//主线程 执行回调函数
				eventBus.invokeSubscriber(pendingPost);
				...
			}
		} finally {
			handlerActive = rescheduled;
		}
	}
}

2)BackgroundPoster backgroundPoster:

订阅者设置了BACKGROUND 模式时,如果EventBus.getDefault().post()调用线程是主线程,
EventBus会调用 BackgroundPoster.enqueue()来调度发送事件。

final class BackgroundPoster implements Runnable, Poster {
	
	/* PendingPostQueue 中维护了一个单链表,用于存储需要在主线程回调的事件
	* 链表元素为 PendingPost
	*/
	private final PendingPostQueue queue;
	private final EventBus eventBus;
	...

	public void enqueue(Subscription subscription, Object event) {
		//事件封装成 PendingPost 对象,塞入队列中
		PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
		synchronized (this) {
			queue.enqueue(pendingPost);
			if (!executorRunning) {
				executorRunning = true;
				//用线程池来执行
				eventBus.getExecutorService().execute(this);
			}
		}
	}

	@Override
	public void run() {
		...
		//线程池中执行
		while (true) {
			//从队列头部开始取出事件
			PendingPost pendingPost = queue.poll(1000);
			...
			//执行回调函数
			eventBus.invokeSubscriber(pendingPost);
		}
		...
	}
}

3)AsyncPoster asyncPoster:
订阅者设置了 ASYNC 模式时,EventBus会调用 AsyncPoster.enqueue()来调度发送事件。

class AsyncPoster implements Runnable, Poster {
	/* PendingPostQueue 中维护了一个单链表,用于存储需要在主线程回调的事件
	* 链表元素为 PendingPost
	*/
	private final PendingPostQueue queue;
	private final EventBus eventBus;
	...
	
	public void enqueue(Subscription subscription, Object event) {
		//把事件构造成一个 PendingPost 对象,塞入队列末尾
		PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
		queue.enqueue(pendingPost);
		//调用线程池,遍历队列,执行回调函数
		eventBus.getExecutorService().execute(this);
	}

	@Override
	public void run() {//线程池线程
		//从队列头部开始取出事件
		PendingPost pendingPost = queue.poll();
		...
		//执行回调函数
		eventBus.invokeSubscriber(pendingPost);
	}
}
2、EventBus 创建实例

1) EventBus.getDefault()

返回一个单例的 EventBus 对象。

2)也可以通过 EventBusBuilder 创建

EventBus.builder()
	.xxx
	.xxx
	.addIndex(SubscriberInfoIndex)//索引加速
	.build();
3、register()
public void register(Object subscriber) {
    Class<?> subscriberClass = subscriber.getClass();
	
	/* 1)findSubscriberMethods()根据Class 查找到 @Subscribe 注解的方法,也是订阅者的回调函数。
	*  2)遍历订阅者的每个回调方法,把每个回调方法和订阅者一起封装成 Subscription
	*  3)返回封装好的回调方法列表
	*/
    List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
    synchronized (this) {
        for (SubscriberMethod subscriberMethod : subscriberMethods) {
            subscribe(subscriber, subscriberMethod);
        }
    }
}

private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
    Class<?> eventType = subscriberMethod.eventType;
    Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
    CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
    if (subscriptions == null) {
        subscriptions = new CopyOnWriteArrayList<>();
		//4)根据优先级把 Subscription 添加到 subscriptionsByEventType 中相应的类的 List 中
        subscriptionsByEventType.put(eventType, subscriptions);
    } 
	...
    
    List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);
    if (subscribedEvents == null) {
        subscribedEvents = new ArrayList<>();
        typesBySubscriber.put(subscriber, subscribedEvents);
    }
	//5)把回调方法订阅的事件,添加到 typesBySubscriber 中对应订阅者的订阅事件List中
    subscribedEvents.add(eventType);

    if (subscriberMethod.sticky) {//如果回调方法由注册粘性事件
        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 {
            //6)从 stickyEvents 中获取相应粘性事件,并
			Object stickyEvent = stickyEvents.get(eventType);
            checkPostStickyEventToSubscription(newSubscription, stickyEvent);
        }
    }
}
// register 完成
4、post()
public void post(Object event) {
	/*currentPostingThreadState 是一个 ThreadLocal 对象
	* 【1】这里通过 threadLocal 获取当前线程的 PostingThreadState 对象
	*/
    PostingThreadState postingState = currentPostingThreadState.get();
    List<Object> eventQueue = postingState.eventQueue;
	//【1.1】把事件放入 当前线程的 postingState 列表中,与线程绑定。
    eventQueue.add(event);
	...
	//【2】循环从 eventQueue 中取出事件
	while (!eventQueue.isEmpty()) {
		postSingleEvent(eventQueue.remove(0), postingState);
	}
	...
}

private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {
    Class<?> eventClass = event.getClass();
    ...
	//【3】获取事件的所有父类,并遍历
	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);
	}
    ...
    if (!subscriptionFound) {
        ...
        post(new NoSubscriberEvent(this, event));
        ...
    }
}

private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class<?> eventClass) {
    CopyOnWriteArrayList<Subscription> subscriptions;
    synchronized (this) {
		//【4】在 subscriptionsByEventType 中,获取 每个事件的订阅者的回调方法
        subscriptions = subscriptionsByEventType.get(eventClass);
    }
    if (subscriptions != null && !subscriptions.isEmpty()) {
		//【5】遍历该事件的所有回调方法
        for (Subscription subscription : subscriptions) {
            ...
            postToSubscription(subscription, event, postingState.isMainThread);
            ...
        }
        return true;
    }
    return false;
}
/* 比根据 ThreadMode ,通过不同的 poster,
* 在对应的线程中,通过反射 invoke 调用回调函数。
*/
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) {
                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;
		...
    }
}
5、unregister()
public synchronized void unregister(Object subscriber) {
	//【1】从 typesBySubscriber 中取出订阅者的所有事件类型
    List<Class<?>> subscribedTypes = typesBySubscriber.get(subscriber);
    if (subscribedTypes != null) {
		//【2】遍历所有事件
        for (Class<?> eventType : subscribedTypes) {
			//【3】在 subscriptionsByEventType 中,相应事件的相应队列中,删掉该订阅者
            unsubscribeByEventType(subscriber, eventType);
        }
		//【4】从 typesBySubscriber 中删除订阅者的事件列表
        typesBySubscriber.remove(subscriber);
    } 
	//unregister 完成
	...
}

private void unsubscribeByEventType(Object subscriber, Class<?> eventType) {
	//在 subscriptionsByEventType 中,相应事件的相应队列中,删掉该订阅者
    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--;
            }
        }
    }
}
6、索引加速

1)注解处理器
索引是在初始化 EventBus时,通过 EventBusBuilder.addIndex(SubscriberInfoIndex index) 方法传进来的。

public class EventBusBuilder {
	
	public EventBusBuilder addIndex(SubscriberInfoIndex index) {
		if(subscriberInfoIndexes == null) {
			subscriberInfoIndexes = new ArrayList<>();
		}
		/* 传进来的索引信息会保存在subscriberInfoIndexes这个List中
		* 后续会通过EventBusBuilder传到相应EventBus的 SubscriberMethodFinder 实例中
		*/
		subscriberInfoIndexes.add(index);
		return this;
	}
}

//索引类
public interface SubscriberInfoIndex {
	//索引类唯一方法,拿到订阅者的信息
	SubscriberInfo getSubscriberInfo(Class<?> subscriberClass);
}

//EventBus 的注解处理器 用于处理 @Subscribe 注解
@SupportedAnnotationTypes("org.greenrobot.eventbus.Subscribe")
@SupportedOptions(value = {"eventBusIndex", "verbose"})
public class EventBusAnnotationProcessor extends AbstractProcessor {
	
	//被注解表示的方法信息 (key:类,value:@Subscribe注解的方法)
	private final ListMap<TypeElement, ExecutableElement> methodsByClass = new ListMap<>();
	
	// checkHasErrors 检查出来的异常方法
	private final Set<TypeElement> classesToSkip = new HashSet<>(); 

	@Override
	public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment env) {
		Messager messager = processingEnv.getMessager();
		try {
			String index = processingEnv.getOptions().get(OPTION_EVENT_BUS_INDEX);
			// 如果没有在gradle中配置apt的argument,编译就会在这里报错
			if (index == null) { 
				messager.printMessage(Diagnostic.Kind.ERROR, "No option " + OPTION_EVENT_BUS_INDEX +
						" passed to annotation processor");
				return false;
			}
			/** ... */
			// 根据注解拿到所有订阅者的回调方法信息
			collectSubscribers(annotations, env, messager); 
			
			// 筛掉不符合规则的订阅者
			checkForSubscribersToSkip(messager, indexPackage); 
			
			if (!methodsByClass.isEmpty()) {
				createInfoIndexFile(index); // 生成索引类
			} 
			/** 打印错误 */
	}

	/** 下面这些方法就不再贴出具体实现了,我们了解它们的功能就行 */
	
	// 遍历annotations,找出所有被注解标识的方法,以初始化methodsByClass
	private void collectSubscribers 
	
	// 过滤掉static,非public和参数大于1的方法
	private boolean checkHasNoErrors 
	
	// 检查 methodsByClass中的各个类,是否存在非public的父类和方法参数
	private void checkForSubscribersToSkip 
	
	/** 下面这三个方法会把 methodsByClass 中的信息写到相应的类中 */
	private void writeCreateSubscriberMethods
	private void createInfoIndexFile
	private void writeIndexLines
}

编译时通过 注解处理器,分析 @Subscribe 注解,利用注解标识的相关类的信息去生成相关的类。

2)注解处理器生成的类:

/** This class is generated by EventBus, do not edit. */
public class MyEventBusIndex implements SubscriberInfoIndex {
private static final Map<Class<?>, SubscriberInfo> SUBSCRIBER_INDEX;
	static {
		SUBSCRIBER_INDEX = new HashMap<Class<?>, SubscriberInfo>();
		// 每有一个订阅者类,就调用一次 putIndex 往索引中添加相关的信息
		putIndex(new SimpleSubscriberInfo(com.xxx.MainActivity.class, true, new SubscriberMethodInfo[] {
			new SubscriberMethodInfo("onEvent", com.xxx.MainActivity.DriverEvent.class, ThreadMode.POSTING, 0, false), 
			// 类中每一个被Subscribe标识的方法都在这里添加进来
		})); 
	}
	// 下面的代码就是EventBusAnnotationProcessor中写死的了
	private static void putIndex(SubscriberInfo info) {
		SUBSCRIBER_INDEX.put(info.getSubscriberClass(), info);
	}

	@Override
	public SubscriberInfo getSubscriberInfo(Class<?> subscriberClass) {
		SubscriberInfo info = SUBSCRIBER_INDEX.get(subscriberClass);
		if (info != null) {
			return info;
		} else {
			return null;
		}
	}
}

编译时注解处理器生成这个索引类,
该类中把所有被 @Subscribe 注解标识的方法信息(包括方法名、方法参数类型等信息)
封装到 SimpleSubscriberInfo中。

我们拿到的索引其实就是以订阅者的类为 Key、SimpleSubscriberInfo为value的哈希表。

索引类在编译时生成,避免了在在EventBus.register()时才去遍历查找生成,
从而把在注册时需要遍历订阅者所有方法的行为,提前到在编译时完成了。

3)索引的使用

SubscriberMethodFinder.findSubscriberMethods()

class SubscriberMethodFinder {

	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);
		}
		...
	}
	
	private List<SubscriberMethod> findUsingInfo(Class<?> subscriberClass) {
		...				
		while (findState.clazz != null) { // 子类找完了,会继续去父类中找
			
			// 获得订阅者类的相关信息
			findState.subscriberInfo = getSubscriberInfo(findState); 
			
			// 上一步能拿到相关信息的话,就开始把方法数组封装成List
			if (findState.subscriberInfo != null) { 
				SubscriberMethod[] array = findState.subscriberInfo.getSubscriberMethods();
				for (SubscriberMethod subscriberMethod : array) {
					if (findState.checkAdd(subscriberMethod.method, subscriberMethod.eventType)) {
						// checkAdd是为了避免在父类中找到的方法是被子类重写的,
						// 此时应该保证回调时执行子类的方法
						findState.subscriberMethods.add(subscriberMethod);
					}
				}
			} else { // 索引中找不到,降级成运行时通过注解和反射去找
				findUsingReflectionInSingleClass(findState);
			}
			// 上下文切换成父类
			findState.moveToSuperclass(); 
		}
		// 找完后,释放FindState进对象池,并返回找到的回调方法
		return getMethodsAndRelease(findState); 
	}
	
	private SubscriberInfo getSubscriberInfo(FindState findState) {
		 // subscriberInfo 已有实例,证明本次查找需要查找上次找过的类的父类
		if (findState.subscriberInfo != null && findState.subscriberInfo.getSuperSubscriberInfo() != null) {
			SubscriberInfo superclassInfo = findState.subscriberInfo.getSuperSubscriberInfo();
			
			 // 确定是所需查找的类
			if (findState.clazz == superclassInfo.getSubscriberClass()) {
				return superclassInfo;
			}
		}
		// 从我们传进来的 subscriberInfoIndexes 中获取相应的订阅者信息
		if (subscriberInfoIndexes != null) {
			for (SubscriberInfoIndex index : subscriberInfoIndexes) {
				SubscriberInfo info = index.getSubscriberInfo(findState.clazz);
				if (info != null) { 
					return info; 
				}
			}
		}
		return null;
	}
}

推荐阅读:
腾讯Bugly干货-老司机教你“飙”EventBus3

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值