1、EventBus概述:
EventBus是Android中发布订阅事件总线框架,将事件的发布者和订阅者分开, 简化组件之间的通信.使用灵活简单,执行效率高
1.1EventBus有三要素:
Event:事件
Publisher:发布者,通过post()发送事件到EventBus, EventBus作为事件分发器或者调度器,将事件通知到Subscriber(订阅者)
Subscriber:订阅者,通过EventBus接受发布者发送的事件
1.2简单使用
- 在build.gradle中 引入eventbus包
implementation'org.greenrobot:eventbus:3.1.1'
1.3注册订阅者
@Override
protected void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
@Override
protected void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
}
注册中如果需要修改EventBust参数中的内容, 可以通过EventBuilder对可进行更改的内容复制
EventBus.builder()
.eventInheritance(false)
.logSubscriberExceptions(false)
.installDefaultEventBus()
.register(this);
通过使用动态注解@Subscribe接受发布者发布的事件
@Subscribe(threadMode=ThreadMode.MAIN)
public void onSubscribe(String name){
Log.e("Subscribe====", "MainActivty===="+name);
}
1.4发布者发布事件
EventBus.getDefault().post("小名发布了任务");
以上便是EventBus的简单使用,下边我们分析一下EventBus中register的源码
2.EventBust 源码讲解
2.1ThreadMode 的四个类型
POSTING:默认事件发布和订阅者都在同一个线程
MAIN:订阅者处理事件在主线程
MAIN_ORDERED:订阅者处理事件再主线程, 与Main不同的是, 订阅者可以在发布者未完成发布时,就能执行代码.
BACKGROUND:订阅者在子线程中处理事件,如果当前发布者在子线程发布事件,那么订阅者是在同一个子线程处理事件
ASYNC:不管订阅者是否在子线程中, 它在处理事件的时候都会重新开启一个线程进行处理
2.2注册流程
通过regist方法开始了解EventBus注册流程的源码
public void register(Object subscriber) {
//获取订阅者 类
Class> subscriberClass = subscriber.getClass();
// 获取订阅者中使用@Subscribe注解的方法, 将方法信息 封装到ScribeMethod中
List subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
//枷锁 线程安全
synchronized (this) {
for (SubscriberMethod subscriberMethod : subscriberMethods) {
//订阅者 与 方法 存储本地
subscribe(subscriber, subscriberMethod);
}
}
}
通过findSubscirberMethods查找订阅类中的订阅方法
List findSubscriberMethods(Class> subscriberClass) {
//现在本地的METHOD_CACHE的map集合中查找,有就返回 没有就继续执行
List subscriberMethods = METHOD_CACHE.get(subscriberClass);
if (subscriberMethods != null) {
return subscriberMethods;
}
//暂定 ignoreGeneratedIndex
if (ignoreGeneratedIndex) {
subscriberMethods = findUsingReflection(subscriberClass);
} else {
/ /通过findSingInfo查找订阅类中的方法
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;
}
}
在findUsingInfo中,通过FindState保存本地的状态数组,查了找 subscribeMethod
private List findUsingInfo(Class> subscriberClass) {
FindState findState = prepareFindState();
findState.initForSubscriber(subscriberClass);
while (findState.clazz != 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 {
findUsingReflectionInSingleClass(findState);
}
findState.moveToSuperclass();
}
return getMethodsAndRelease(findState);
}
在 SubscirbeMethodFinder类中, 存在一个FIND_STATE_POOL FindState[]数组, 他的作用是1.对订阅类中订阅方法校验 2. 用来做缓存, preparedFindState在数组中取出findState,如果没有就重新创建. 这样减少了频繁创建对象的内存开销.
如果findState中没有subscribeInfo的信息, 就会通过findUsingReflectionInSingleClass() 进行反射,获取到订阅类中符合条件的 订阅方法,并且赋值给FindState中的subscribeMthods集合中.
private void findUsingReflectionInSingleClass(FindState findState) {
Method[] methods;
try {
// 通过反射拿到订阅类的方法
methods = findState.clazz.getDeclaredMethods();
} catch (Throwable th) {
// Workaround for java.lang.NoClassDefFoundError, see https://github.com/greenrobot/EventBus/issues/149
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 subscribeAnnotation = method.getAnnotation(Subscribe.class);
if (subscribeAnnotation != null) {
Class> eventType = parameterTypes[0];
//通过findState对方法进行校验
if (findState.checkAdd(method, eventType)) {
ThreadMode threadMode = subscribeAnnotation.threadMode();
//将符合条件的方法添加到findState的subscirbermethod中
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)) {
String methodName = method.getDeclaringClass().getName() + "." + method.getName();
throw new EventBusException(methodName +
" is a illegal @Subscribe method: must be public, non-static, and non-abstract");
}
}
}
最终通过 getMethodsAndRelease 返回订阅类中订阅方法集合以及加入到METHOD_CACHE中.
获取到 订阅类中的方法后,对方法集合进行循环, 将方法与类以及方法参数类型 重组, 分别 加入subscriptionsByEventType map和 typesBySubscriber map中.
// Must be called in synchronized block
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
Class> eventType = subscriberMethod.eventType;
Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
CopyOnWriteArrayList subscriptions = subscriptionsByEventType.get(eventType);
if (subscriptions == null) {
subscriptions = new CopyOnWriteArrayList<>();
//j参数类型 为key值, value subscription 是当前订阅类和订阅方法属性的封装对象
subscriptionsByEventType.put(eventType, subscriptions);
} else {
if (subscriptions.contains(newSubscription)) {
throw new EventBusException("Subscriber " + subscriber.getClass() + " already registered to event "
+ eventType);
}
}
//根据优先级重置
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;
}
}
//订阅者为key值, 方法类型的集合为value
List> subscribedEvents = typesBySubscriber.get(subscriber);
if (subscribedEvents == null) {
subscribedEvents = new ArrayList<>();
typesBySubscriber.put(subscriber, subscribedEvents);
}
subscribedEvents.add(eventType);
if (subscriberMethod.sticky) {
if (eventInheritance) {
// Existing sticky events of all subclasses of eventType have to be considered.
// Note: Iterating over all events may be inefficient with lots of sticky events,
// thus data structure should be changed to allow a more efficient lookup
// (e.g. an additional map storing sub classes of super classes: Class -> List).
Set, Object>> entries = stickyEvents.entrySet();
for (Map.Entry, 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);
}
}
}