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. UVa1354 Mobile Computing
  2. VTK:PolyData之RotationAroundLine
  3. P4248 [AHOI2013]差异
  4. OPENSSL X509证书验证
  5. pwn和逆向的区别_Pwn之简单patch
  6. R+NLP︱text2vec包——BOW词袋模型做监督式情感标注案例(二,情感标注)
  7. 重大危机引发的公司经营战略问题回顾
  8. modbus功能码04实例_MODBUS功能码简介
  9. 高洛峰细说php百度贴吧_高洛峰细说PHP视频教程推荐
  10. Linux7(CentOs7.5)安装ssh、和修改ssh端口号
  11. 【手把手带你Godot游戏开发】Godot界面介绍
  12. 域外计算机无法连接远程桌面,如何开启域内计算机的远程桌面连接?
  13. iOS定位经纬度转换
  14. R语言 kNN 对鸢尾花进行分类
  15. php guzzlehttp,PHP HTTP客户端-Guzzle原理解析
  16. 100W个微信红包封面,人人都能领取到!!!
  17. 【转载】为什么样本方差(sample variance)的分母是 n-1?
  18. 第四章 ContextCapture 19 空三控制点平差
  19. 达梦数据库定位阻塞方法举例
  20. 独立后台月老办事处一元交友盲盒微信小程序源码下载,可自定义价格

热门文章

  1. php excel 进度,在php中生成Excel文件时显示进度条
  2. 如何让Word 2003识别Docx文件
  3. CDP产品大观之“准CDP”
  4. Zabbix监控系统的搭建
  5. Mezzanine user 扩展
  6. [C语言]函数(function)
  7. Java程序员的重启人生-1.初到异世界
  8. macOS更新系统到12.6后git无法使用
  9. 一种结合基于股债利差的A股估值百分位、有限价值策略定投和股债组合投资的创新型低回撤高收益稳健理财方法
  10. 为什么要数据归一化和归一化方法