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. 手机网站优化重点来了!快记下
  2. eclipse断点调试 出现Source not found
  3. Netty原理五:ChannelFuture、DefaultChannelPromise对象解析
  4. [Java] 蓝桥杯 BASIC-8 基础练习 回文数
  5. 【链表】删除链表的倒数第n个节点
  6. 洛谷P1074 靶形数独 [搜索]
  7. Android中Context的详细介绍
  8. 空气质量模型:操作指南与案例研究(模型概述)
  9. 如何设置ddns动态域名服务实现外网访问
  10. 随机森林+python代码实现
  11. 邮票问题(两张邮票)
  12. html表格制作旅游网页,简单实用的网页表格特效_html
  13. mysql数据库总是自动关闭_急求关于mysql数据库自动停止的问题
  14. 创新创意ssm计算机毕业设计题目300例之java农商行贷款管理系统f1gnk
  15. SQL创建某一年日历表
  16. Dave Oracle 学习 手册 第一版 下载 说明
  17. CSS3_01_圆角_边框_渐变_字体
  18. 【暑假复习】【搜索】POJ3009:Curling 2.0
  19. matlab 历史波动率,如何用Excel统计历史波动率
  20. unity 导出模型为fbx 格式

热门文章

  1. ansys apdl的使用方法
  2. 那一抹淡淡的汐蓝 (瀑瀑安)
  3. js对象、数字深拷贝方式(转)
  4. Verilog状态机详述
  5. TI-Davinci开发系列之七DVSDK-4.03目录介绍
  6. AI全自动原创视频生成器-震撼来袭
  7. 让慢行回归城市—佛山祖庙商圈慢行系统改善工程
  8. 计算机显示适配器禁用了电脑黑屏,Win10电脑禁用集成显卡后黑屏如何解决_Win10系统禁用集成显卡后黑屏解决方案...
  9. 【计算机网络】互联网上的音频/视频服务
  10. 吴恩达《深度学习》课程介绍