2种思路去读EventBus源码

1.注册 EventBus.getDefault().register(this);

2.发送消息EventBus.getDefault().post();

根据1追到了findSubscriberMethodsWithReflection   根据反射查找订阅者,代码如下里面的内容不解释了,返回的是一个订阅方法的集合。

private List<SubscriberMethod> findSubscriberMethodsWithReflection(Class<?> subscriberClass) {List<SubscriberMethod> subscriberMethods = new ArrayList<SubscriberMethod>();Class<?> clazz = subscriberClass;HashSet<String> eventTypesFound = new HashSet<String>();StringBuilder methodKeyBuilder = new StringBuilder();while (clazz != null) {String name = clazz.getName();if (name.startsWith("java.") || name.startsWith("javax.") || name.startsWith("android.")) {// Skip system classes, this just degrades performancebreak;}// Starting with EventBus 2.2 we enforced methods to be public (might change with annotations again)Method[] methods = clazz.getDeclaredMethods();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) {String methodName = method.getName();Class<?> eventType = parameterTypes[0];methodKeyBuilder.setLength(0);methodKeyBuilder.append(methodName);methodKeyBuilder.append('>').append(eventType.getName());String methodKey = methodKeyBuilder.toString();if (eventTypesFound.add(methodKey)) {// Only add if not already found in a sub classThreadMode threadMode = subscribeAnnotation.threadMode();subscriberMethods.add(new SubscriberMethod(method, eventType, threadMode,subscribeAnnotation.priority(), subscribeAnnotation.sticky()));}}} else if (strictMethodVerification) {if (method.isAnnotationPresent(Subscribe.class)) {String methodName = name + "." + method.getName();throw new EventBusException("@Subscribe method " + methodName +"must have exactly 1 parameter but has " + parameterTypes.length);}}} else if (strictMethodVerification) {if (method.isAnnotationPresent(Subscribe.class)) {String methodName = name + "." + method.getName();throw new EventBusException(methodName +" is a illegal @Subscribe method: must be public, non-static, and non-abstract");}}}clazz = clazz.getSuperclass();}return subscriberMethods;
}

然后看调用这个方法的地方

public void register(Object subscriber) {Class<?> subscriberClass = subscriber.getClass();// @Subscribe in anonymous classes is invisible to annotation processing, always fall back to reflectionboolean forceReflection = subscriberClass.isAnonymousClass();List<SubscriberMethod> subscriberMethods =subscriberMethodFinder.findSubscriberMethods(subscriberClass, forceReflection);for (SubscriberMethod subscriberMethod : subscriberMethods) {subscribe(subscriber, subscriberMethod);}
}

接下来咱们继续查看 subscribe(subscriber, subscriberMethod);,如下

划线部分核心代码,到此为止EventBus.getDefault().register(this);大概干了一这样一件事情

通过反射得到观察者(订阅者)的方法,事件和所在的线程

然后将这些参数组装后放入Map中,其中key为事件类型

// Must be called in synchronized block
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {Class<?> eventType = subscriberMethod.eventType;CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType);Subscription newSubscription = new Subscription(subscriber, subscriberMethod);if (subscriptions == null) {subscriptions = new CopyOnWriteArrayList<Subscription>();subscriptionsByEventType.put(eventType, subscriptions);} else {if (subscriptions.contains(newSubscription)) {throw new EventBusException("Subscriber " + subscriber.getClass() + " already registered to event "+ eventType);}}// Starting with EventBus 2.2 we enforced methods to be public (might change with annotations again)// subscriberMethod.method.setAccessible(true);// Got to synchronize to avoid shifted positions when adding/removing concurrentlysynchronized (subscriptions) {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;}}}List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);if (subscribedEvents == null) {subscribedEvents = new ArrayList<Class<?>>();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<Class>).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 {Object stickyEvent = stickyEvents.get(eventType);checkPostStickyEventToSubscription(newSubscription, stickyEvent);}}
}

-----------------------------------------------------------------------------------------------------------------------------

接下来看一下发送消息是怎么实现的

/** Posts the given event to the event bus. */
public void post(Object event) {PostingThreadState postingState = currentPostingThreadState.get();List<Object> eventQueue = postingState.eventQueue;eventQueue.add(event);if (!postingState.isPosting) {postingState.isMainThread = Looper.getMainLooper() == Looper.myLooper();postingState.isPosting = true;if (postingState.canceled) {throw new EventBusException("Internal error. Abort state was not reset");}try {while (!eventQueue.isEmpty()) {postSingleEvent(eventQueue.remove(0), postingState);}} finally {postingState.isPosting = false;postingState.isMainThread = false;}}
}

接着看画线部分方法,然后此方法中找到调用的postSingleEventForEventType(Object event, PostingThreadState postingState, Class<?> eventClass)方法。划线部分是核心代码,头一个划线部分是从map中根据发送事件类型得到的一个类。这个类存储的是订阅的方法,所在的线程,不出意外的话下面应该用的是反射调用订阅的方法。拭目以待

private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class<?> eventClass) {CopyOnWriteArrayList<Subscription> subscriptions;synchronized (this) {subscriptions = subscriptionsByEventType.get(eventClass);}if (subscriptions != null && !subscriptions.isEmpty()) {for (Subscription subscription : subscriptions) {postingState.event = event;postingState.subscription = subscription;boolean aborted = false;try {postToSubscription(subscription, event, postingState.isMainThread);aborted = postingState.canceled;} finally {postingState.event = null;postingState.subscription = null;postingState.canceled = false;}if (aborted) {break;}}return true;}return false;
}

接下来咱们看一下第二个划线部分的代码。里面基本全是反射

/**

*subscription   里面存储的是要调用方法的名字等信息

*event   此事件

*isMainThread  boolean 当前发送消息线程是不是UI主线程

*/

private void postToSubscription(Subscription subscription, Object event, boolean。isMainThread) {switch (subscription.subscriberMethod.threadMode) {  //当时订阅方法所在的线程case PostThread:   //非主线程invokeSubscriber(subscription, event);break;case MainThread:  //ui主线程if (isMainThread) { //在主线程直接更新invokeSubscriber(subscription, event);} else { //通过handler发送消息,防止在自线程中更新UI的误操作mainThreadPoster.enqueue(subscription, event);}break;case BackgroundThread:if (isMainThread) { //主线程创建runable丢入线程池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);}
}

EventBus底层实现原理相关推荐

  1. vue中EventBus的实现原理

    通常我们在组件之间的通信的时候常常会使用到eventbus解决同胞组件之间的传值,但是一直都搞不懂eventBus的实现原理,今天我就给大家分享一下eventBus底层的原理,不对的地方希望大家多多指 ...

  2. Java并发机制的底层实现原理

    Java代码在编译后会变成Java字节码,字节码被类加载器加载到JVM里,JVM执行字节码,最终需要转化为汇编指令在CPU上执行,Java中所使用的并发机制依赖于JVM的实现和CPU的指令.本章我们将 ...

  3. HashMap底层实现原理,红黑树,B+树,B树的结构原理,volatile关键字,CAS(比较与交换)实现原理

    HashMap底层实现原理,红黑树,B+树,B树的结构原理,volatile关键字,CAS(比较与交换)实现原理 首先HashMap是Map的一个实现类,而Map存储形式是键值对(key,value) ...

  4. Spring AOP概述及底层实现原理

    Spring AOP概述及底层实现原理 aop概述 AOP全称为Aspect Oriented Programming的缩写,意为:面向切面编程.将程序中公用代码进行抽离,通过动态代理实现程序功能的统 ...

  5. java底层原理书籍_阿里面试题:Java中this和super关键字的底层实现原理

    知道的越多,不知道的就越多,业余的像一棵小草! 编辑:业余草 来源:https://www.xttblog.com/?p=5028 B 站:业余草 最近一个粉丝加我说,接到了阿里的面试,问问我阿里会面 ...

  6. Spring(二)IOC底层实现原理

    IOC原理 将对象创建交给Spring去管理. 实现IOC的两种方式 IOC配置文件的方式 IOC注解的方式 IOC底层实现原理 底层实现使用的技术 1.1 xml配置文件 1.2 dom4j解析xm ...

  7. 《Java并发编程的艺术》一一第2章Java并发机制的底层实现原理

    第2章Java并发机制的底层实现原理 2.1 volatile的应用 Java代码在编译后会变成Java字节码,字节码被类加载器加载到JVM里,JVM执行字节码,最终需要转化为汇编指令在CPU上执行, ...

  8. Java多线程之线程池7大参数、底层工作原理、拒绝策略详解

    Java多线程之线程池7大参数详解 目录 企业面试题 线程池7大参数源码 线程池7大参数详解 底层工作原理详解 线程池的4种拒绝策略理论简介 面试的坑:线程池实际中使用哪一个? 1. 企业面试题 蚂蚁 ...

  9. HashMap底层实现原理/HashMap与HashTable区别/HashMap与HashSet区别(转)

    HashMap底层实现原理/HashMap与HashTable区别/HashMap与HashSet区别 文章来源:http://www.cnblogs.com/beatIteWeNerverGiveU ...

最新文章

  1. .net实现md5加密 sha1加密 sha256加密 sha384加密 sha512加密 des加密解密
  2. vue-auto-focus: 控制自动聚焦行为的 vue 指令
  3. JQuery-学习笔记02【基础——JQuery选择器】
  4. 两种通过代码访问SalesOrder header text内容的办法
  5. hdu 4267 多维树状数组
  6. LeetCode 1538. Guess the Majority in a Hidden Array
  7. Golang Web入门(2):如何实现一个RESTful风格的路由
  8. 提交代码到远程GIT仓库,代码自动同步到远程服务器上。
  9. Nginx完美解决前后端分离端口号不同导致的跨域问题
  10. android自定义控件动态,GitHub - itrenjunhua/WaveView: Android自定义控件实现动态百分比水波纹效果...
  11. 360胡宁:通往CTO的道路上就是四个字
  12. 蓝桥杯省赛JavaB组真题
  13. 3G中的A-GPS移动定位技术
  14. Excel 操作 第一篇 行列技巧
  15. 新手使用python易踩坑语法:if语句中or 与in连用
  16. bootstrap4--概述与页面创建
  17. 猪齿鱼平台CI流程总结--遇到的坑
  18. 谷歌浏览器Chrome,TableExport.js 导出时数据量过大报网络错误的问题
  19. 华为如何在开发者选项观察错误日志_爬虫scrapy框架--log日志输出配置及使用
  20. 仿微信、微博发朋友圈,文字+图片+视频

热门文章

  1. 庄懂的TA笔记(六)<FakeEnvReflect 生锈,锈迹效果>
  2. 信息流广告投放的技巧
  3. 什么时候需要动态分配内存?
  4. 英伟达发布528.02 WHQL 新驱动,支持4070 Ti
  5. 怎么把视频内存压缩小?视频内存过大怎么压缩?
  6. vue-cli搭建项目,使用localhost或ip地址均可访问
  7. FFE均衡技术的原理、作用及特点
  8. 《C指针》学习笔记( 第四、五章)指针与字符串、指针与多维数组
  9. 计算机术语access,计算机英语词汇术语:access(存取,访问)
  10. 【Pandas】数据分析工具Pandas的基本操作和可视化工具Matplotlib