EventBus方法:
onEventMainThread(发送时实参类型)
将接收到的数据,在主线程中执行
onEventPostThread(发送时实参类型)
将接收到的数据,在发送时的线程中进行执行
onEventAsync(发送时实参类型)
将接收到的数据,直接放在线程池中进行执行
onEventBackGroundThread(发送时实参类型)
将接收到的数据,如果发送时在非UI线程中,则直接在发送线程中执行,否则在线程池中一个接一个执行
EventBus.default():
实际上就是一个单利,创建对象的过程,使用了双if判断以及同步锁,防止并发访问
public static EventBus getDefault() {
if(defaultInstance == null) {
Class var0 = EventBus.class;
synchronized(EventBus.class) {
if(defaultInstance == null) {
defaultInstance = new EventBus();
}
}
}return defaultInstance;
}
EventBus.default().register():
实际上不管是几个参数的register调用的都是同一个,去匹配类中符合EventBus命名规则的方法
private synchronized void register(Object subscriber, boolean sticky, int priority) {
//findSubscriberMethods这个方法就是去匹配方法 封装进map
List subscriberMethods = this.subscriberMethodFinder.findSubscriberMethods(subscriber.getClass());
//所有方法都去调用subscribe方法
Iterator i$ = subscriberMethods.iterator();
while(i$.hasNext()) {
SubscriberMethod subscriberMethod = (SubscriberMethod)i$.next();
this.subscribe(subscriber, subscriberMethod, sticky, priority);
}}
findSubscriberMethods:
在调用这个方法的时候去使用传过来的当前类.class , 调用getMethod方法得到当前类中所有的方法,然后开始遍历
判断是否是onEvent开头,是否是public修饰,是否非static或者abstract修饰的方法,是否只有一个实参,满足上述所有
条件才进入到封装部分,根据方法名的结尾是否以MainThread或PostThread或Async或BackGroundThread结尾如果不以这四个
其中一个结尾则continue跳出当前循环,进行下一次循环,如果都不匹配则抛异常。匹配上之后根据不同的后缀设置不同的ThreadMode(执行的线程的模式)
在方法匹配完毕的时候获取方法中实参的数据类型 eventType,最后将方法method,threadMode,eventType存入名叫subscriberMethods(在下面方法中这个方 法名叫var23)(订阅者方法)的List集合中
然后返回
List findSubscriberMethods(Class> subscriberClass) {
String key = subscriberClass.getName();
Map clazz = methodCache;
List subscriberMethods;
synchronized(methodCache) {
//对于methodCache这个集合 我的理解是所有被register的类 类名做键,类中的所有onEvent开头的方法放进一个List集合做值 都存储在这个集合里面
//那么这段代码显而易见,就是你注册的这个类中存储着所有onEvent开头的方法的集合
//而事实上一个被注册的类中的所有onEvent方法都在subscriberMethods里面
subscriberMethods = (List)methodCache.get(key);
}//判断通过类名获取到的装着onEvent方法的集合是否为空,如果不为空,那么就是封装过了 直接返回
if(subscriberMethods != null) {
return subscriberMethods;
} else {
ArrayList var23 = new ArrayList();
Class var24 = subscriberClass;
HashSet eventTypesFound = new HashSet();
//看这里的getSuperclass register这个方法它不仅扫描了当前类 连带着当前类的所有父类也扫描了
for(StringBuilder methodKeyBuilder = new StringBuilder();
var24 != null;
var24 = var24.getSuperclass()) {//这里是在判断register的类它是否是系统包中的东西排除java. javax. android.
String name = var24.getName();
if(name.startsWith("java.") || name.startsWith("javax.") || name.startsWith("android.")) {
break;
}//这个地方就是通过反射获取类中所有的方法
Method[] methods = var24.getDeclaredMethods();
Method[] arr$ = methods;
int len$ = methods.length;
//开始遍历每一个方法去匹配 去封装
for(int i$ = 0;
i$ < len$;
++i$) {
Method method = arr$[i$];
String methodName = method.getName();
//判断方法名是否是以onEvent开头
if(methodName.startsWith("onEvent")) {
int modifiers = method.getModifiers();
//这里开始我也看不懂 后来看了下鸿洋大神的CSDN博客 知道了这里是判断是否是public修饰的
//并且不是static和abstract修饰的方法
if((modifiers & 1) != 0 && (modifiers & 5192) == 0) {
Class[] parameterTypes = method.getParameterTypes();
//这里是判断方法的实参是否只有一个
if(parameterTypes.length == 1) {
String modifierString = methodName.substring("onEvent".length());
//符合以上所有的就去看看onEvent后面的 究竟是匹配哪种模式
ThreadMode threadMode;
//onEvent
if(modifierString.length() == 0) {
threadMode = ThreadMode.PostThread;
//onEventMainThread
} else if(modifierString.equals("MainThread")) {
threadMode = ThreadMode.MainThread;
//onEventBackgroundThread
} else if(modifierString.equals("BackgroundThread")) {
threadMode = ThreadMode.BackgroundThread;
} else {
//这里如果不匹配上面四个那么就看看是否匹配onEventAsync
if(!modifierString.equals("Async")) {
if(!this.skipMethodVerificationForClasses.containsKey(var24)) {
throw new EventBusException("Illegal onEvent method, check for typos: " + method);
}
continue;
}threadMode = ThreadMode.Async;
}//这里的eventType我上面介绍的时候说了就是实参的类型用来做key的
Class eventType = parameterTypes[0];
methodKeyBuilder.setLength(0);
methodKeyBuilder.append(methodName);
methodKeyBuilder.append('>').append(eventType.getName());
String methodKey = methodKeyBuilder.toString();
if(eventTypesFound.add(methodKey)) {
//存进了var23的集合里面 里面有method threadMode eventType
var23.add(new SubscriberMethod(method, threadMode, eventType));
}
}
} else if(!this.skipMethodVerificationForClasses.containsKey(var24)) {
Log.d(EventBus.TAG, "Skipping method (not public, static or abstract): " + var24 + "." + methodName)
}
}
}
}
//走完之后如果var23方法还是空那么就抛个异常
if(var23.isEmpty()) {
throw new EventBusException("Subscriber " + subscriberClass + " has no public methods called " + "onEvent");
} else {
//不然就返回了
Map var25 = methodCache;
synchronized(methodCache) {
methodCache.put(key, var23);
return var23;
}
}
}
}
回到register,迭代器遍历subscriberMethods集合得到每一个subscriberMethod方法调用subscribe方法
Iterator i$ = subscriberMethods.iterator();
while(i$.hasNext()) {
SubscriberMethod subscriberMethod = (SubscriberMethod)i$.next();
//传入了subscriber当前类 subscriberMethod当前类中的onEvent开头的方法 peiority优先级
this.subscribe(subscriber, subscriberMethod, sticky, priority);
}
在subscribe方法中通过eventType(实参类型)去subScriptionByEventType中查找存储在该集合中的方法,顺便把我们传入的实参封装成了subscription,
如果没有找到则创建。根据实参类型找到所有匹配的方法之后,根据优先级将新创建的存储着对应方法的集合插入进存储匹配方法的集合中,插入完数据之后
再使用eventType做键存储着对应方法的集合(subscribedEvents)做值存储进subScriptionByEventType集合中
最后判断sticky,如果为true,根据eventType(实参类型)去stickyEvents(存储着sticky的map)中去查找对应的stickyEvent,如果有对应的则立即发布出去
stickyEvent实际上就是我们post时的实参
在这个方法中实际上就是做了一件事:扫描了所有的方法,最终把匹配到的方法保存到了subsriptionByEventType这个键值对的map中,其中key就是我们方法中实参的类型(eventType)
value就是存储着这个eventType匹配的所有方法
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod, boolean sticky, int priority) {
//subscriberMethod 上面封装的时候 里面有三个参数 method threadMode eventType
//这里获取到eventType的类型 也就是onEvent方法的实参类型
Class eventType = subscriberMethod.eventType;
//在subscriptionsByEventType里面通过这个eventType去获取匹配的方法 subscriptionsByEventType这个map里面存储了当前类中所有onEvent开头的方法
CopyOnWriteArrayList subscriptions = (CopyOnWriteArrayList)this.subscriptionsByEventType.get(eventType);
//封装当前这个onEvent方法的类 包括当前类 onEvent方法 优先级如果理解不了可以理解成一个bean
Subscription newSubscription = new Subscription(subscriber, subscriberMethod, priority);
//判断从subscriptionsByEventType通过key获取到的onEvent方法的集合是否为空
if(subscriptions == null) {
//为空则创建 并且添加进subscriptionsByEventType
subscriptions = new CopyOnWriteArrayList();
this.subscriptionsByEventType.put(eventType, subscriptions);
//不为空 并且包含newSubscription 这个就是上面的封装了当前类 onEvent方法 优先级的bean如果包含的话 那么就是说这个eventType类型的参数已经存在了
//如果已经存在不进行判断 那么到发布道订阅者的时候就会分不清到底是哪一个 产生了耦合
} else if(subscriptions.contains(newSubscription)) {
throw new EventBusException("Subscriber " + subscriber.getClass() + " already registered to event " + eventType);
}//这里就是遍历onEvent方法从if判断可以看出 根据优先级进行插入优先级越高就插入到集合的越前面
int size = subscriptions.size();
for(int subscribedEvents = 0;
subscribedEvents <= size;
++subscribedEvents) {
if(subscribedEvents == size || newSubscription.priority > ((Subscription)subscriptions.get(subscribedEvents)).priority) {
subscriptions.add(subscribedEvents, newSubscription);
break;
}
}//根据subscriber去存储着eventType和subscriber的map里面找到存储着subscriber中所有eventType的集合
Object var14 = (List)this.typesBySubscriber.get(subscriber);
//判断是否为null
if(var14 == null) {
//为null则创建
var14 = new ArrayList();
//存储进装着subscriber和eventType的map
this.typesBySubscriber.put(subscriber, var14);
}
//把eventType添加进集合
((List)var14).add(eventType);
//判断sticky是否为true 如果为true就根据eventType去获取stickyEvents (stickyEvents实际上就是我们post时的参数)
if(sticky) {
Map var11 = this.stickyEvents;
Object stickyEvent;
synchronized(this.stickyEvents) {
stickyEvent = this.stickyEvents.get(eventType);
}
//如果有的话就发布出去
if(stickyEvent != null) {
this.postToSubscription(newSubscription, stickyEvent, Looper.getMainLooper() == Looper.myLooper());
}
}}
post方法:
进入到post方法首先获取到postingstate,然后把post的实参添加到postingstate的eventQueue中,然后判断了当前的post方法是否在执行,如果当前post方法正在被执行那么就直接return
这个判断是为了防止post方法被多次执行,在执行的时候会把这个判断的条件isPosting赋值为true,在执行完毕之后赋值为false
在判断当前post是否在执行之后,执行当前post方法的时候判断是否是在主线程中执行,为postingstate的isMainThread赋值
然后遍历eventQueue得到所有event调用postSingleEvent方法
在postSingleEvent方法中得到post实参的类型,也就是register存储到subScriptionByEvent这个map中的键,然后通过这个eventType去循环遍历这个map获取到匹配的方法
然后依次去调用postToSubscription方法这个方法就是反射执行方法了
postToSubscription:
在这个方法中通过传过来的subScriptionByEvent中的value中的threadMode去判断在哪个线程中执行(MainThread、PostThread、Async、BackgroundThread)
post方法实际上就是根据参数去查找方法,然后通过反射区调用
public void post(Object event) {
//首先获取到postingstate包含了一个eventQueue和一些标志位。
EventBus.PostingThreadState postingState = (EventBus.PostingThreadState)this.currentPostingThreadState.get();
//先得到eventQueue
List eventQueue = postingState.eventQueue;
//把当前这个post的实参也加入到event队列中
eventQueue.add(event);
//判断当前的post方法是否正在被执行 如果是正在被执行不去管它
if(!postingState.isPosting) {
//判断是否在主线程中执行
postingState.isMainThread = Looper.getMainLooper() == Looper.myLooper();
//在进入这个判断之后把这个判断条件置为true 代表当前有post方法正在执行
postingState.isPosting = true;
if(postingState.canceled) {
throw new EventBusException("Internal error. Abort state was not reset");
}//这个就是遍历eventQueue查找方法 反射调用 调用一个 删除一个
try {
while(!eventQueue.isEmpty()) {
this.postSingleEvent(eventQueue.remove(0), postingState);
}
} finally {
postingState.isPosting = false;
postingState.isMainThread = false;
}
}}
【Eventbus 学习完毕后的总结】
postSingleEvent:
private void postSingleEvent(Object event, EventBus.PostingThreadState postingState) throws Error {
//得到post方法的实参
Class eventClass = event.getClass();
boolean subscriptionFound = false;
if(this.eventInheritance) {
//这段获取到所有类型的集合
List eventTypes = this.lookupAllEventTypes(eventClass);
int countTypes = eventTypes.size();
//获取每一个类型
for(int h = 0;
h < countTypes;
++h) {
Class clazz = (Class)eventTypes.get(h);
//通过类型去获取方法
subscriptionFound |= this.postSingleEventForEventType(event, postingState, clazz);
}
} else {
subscriptionFound = this.postSingleEventForEventType(event, postingState, eventClass);
}if(!subscriptionFound) {
if(this.logNoSubscriberMessages) {
Log.d(TAG, "No subscribers registered for event " + eventClass);
}if(this.sendNoSubscriberEvent && eventClass != NoSubscriberEvent.class && eventClass != SubscriberExceptionEvent.class) {
this.post(new NoSubscriberEvent(this, event));
}
}}
postSingleEventForEventType:
private boolean postSingleEventForEventType(Object event, EventBus.PostingThreadState postingState, Class> eventClass) {
//先定义一个用来存储onEvent方法的集合
CopyOnWriteArrayList subscriptions;
synchronized(this) {
//通过传过来的类型去获取onEvent方法
subscriptions = (CopyOnWriteArrayList)this.subscriptionsByEventType.get(eventClass);
}
//不为空遍历每个方法
if(subscriptions != null && !subscriptions.isEmpty()) {
Iterator i$ = subscriptions.iterator();
while(i$.hasNext()) {
Subscription subscription = (Subscription)i$.next();
postingState.event = event;
postingState.subscription = subscription;
boolean aborted = false;
try {
//遍历到之后这个方法就开始反射调用方法了
this.postToSubscription(subscription, event, postingState.isMainThread);
aborted = postingState.canceled;
} finally {
postingState.event = null;
postingState.subscription = null;
postingState.canceled = false;
}if(aborted) {
break;
}
}return true;
} else {
return false;
}
}
postToSubscription:
//反射调用对应的方法
private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {
//之前存的threadMode在这里排上用场了
switch(EventBus.SyntheticClass_1.$SwitchMap$de$greenrobot$event$ThreadMode[subscription.subscriberMethod.threadMode.ordinal()]) {
case 1:
//直接在发送post的线程执行
this.invokeSubscriber(subscription, event);
break;
case 2:
//判断post的线程是否是主线程
if(isMainThread) {
this.invokeSubscriber(subscription, event);
} else {
//在主线程执行
this.mainThreadPoster.enqueue(subscription, event);
}
break;
case 3:
if(isMainThread) {
//在主线程执行
this.backgroundPoster.enqueue(subscription, event);
} else {
//在post的线程执行
this.invokeSubscriber(subscription, event);
}
break;
case 4:
//异步执行
this.asyncPoster.enqueue(subscription, event);
break;
default:
throw new IllegalStateException("Unknown thread mode: " + subscription.subscriberMethod.threadMode);
}}
--------------------------------------------------------------------------------------------------------------------------------------------
总算是搞完了,小弟菜鸟一枚,总结纯属加深理解,有不对的地方,还请指教。
推荐阅读
- 从零开发一个完整的Android项目(九)——图片浏览
- Android开发|ViewPager自适应高度问题
- Android|Android 指定销毁一个Activity
- 【Android】简单图片浏览器
- 理解ButterKnife(自动生成绑定资源的代码)
- MAC下搭建Android Studio
- NestedScrollingParent 和NestedScrollingChild 实现嵌套滑动
- android用shape画一条横线
- 华为推送 的坑
- Duplicate class com.alipay.a.a.a found in modules classes.jar (:alipaySdk-15.6.2-20190416165036:) an