EventBus底层实现原理
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底层实现原理相关推荐
- vue中EventBus的实现原理
通常我们在组件之间的通信的时候常常会使用到eventbus解决同胞组件之间的传值,但是一直都搞不懂eventBus的实现原理,今天我就给大家分享一下eventBus底层的原理,不对的地方希望大家多多指 ...
- Java并发机制的底层实现原理
Java代码在编译后会变成Java字节码,字节码被类加载器加载到JVM里,JVM执行字节码,最终需要转化为汇编指令在CPU上执行,Java中所使用的并发机制依赖于JVM的实现和CPU的指令.本章我们将 ...
- HashMap底层实现原理,红黑树,B+树,B树的结构原理,volatile关键字,CAS(比较与交换)实现原理
HashMap底层实现原理,红黑树,B+树,B树的结构原理,volatile关键字,CAS(比较与交换)实现原理 首先HashMap是Map的一个实现类,而Map存储形式是键值对(key,value) ...
- Spring AOP概述及底层实现原理
Spring AOP概述及底层实现原理 aop概述 AOP全称为Aspect Oriented Programming的缩写,意为:面向切面编程.将程序中公用代码进行抽离,通过动态代理实现程序功能的统 ...
- java底层原理书籍_阿里面试题:Java中this和super关键字的底层实现原理
知道的越多,不知道的就越多,业余的像一棵小草! 编辑:业余草 来源:https://www.xttblog.com/?p=5028 B 站:业余草 最近一个粉丝加我说,接到了阿里的面试,问问我阿里会面 ...
- Spring(二)IOC底层实现原理
IOC原理 将对象创建交给Spring去管理. 实现IOC的两种方式 IOC配置文件的方式 IOC注解的方式 IOC底层实现原理 底层实现使用的技术 1.1 xml配置文件 1.2 dom4j解析xm ...
- 《Java并发编程的艺术》一一第2章Java并发机制的底层实现原理
第2章Java并发机制的底层实现原理 2.1 volatile的应用 Java代码在编译后会变成Java字节码,字节码被类加载器加载到JVM里,JVM执行字节码,最终需要转化为汇编指令在CPU上执行, ...
- Java多线程之线程池7大参数、底层工作原理、拒绝策略详解
Java多线程之线程池7大参数详解 目录 企业面试题 线程池7大参数源码 线程池7大参数详解 底层工作原理详解 线程池的4种拒绝策略理论简介 面试的坑:线程池实际中使用哪一个? 1. 企业面试题 蚂蚁 ...
- HashMap底层实现原理/HashMap与HashTable区别/HashMap与HashSet区别(转)
HashMap底层实现原理/HashMap与HashTable区别/HashMap与HashSet区别 文章来源:http://www.cnblogs.com/beatIteWeNerverGiveU ...
最新文章
- 手机网站优化重点来了!快记下
- eclipse断点调试 出现Source not found
- Netty原理五:ChannelFuture、DefaultChannelPromise对象解析
- [Java] 蓝桥杯 BASIC-8 基础练习 回文数
- 【链表】删除链表的倒数第n个节点
- 洛谷P1074 靶形数独 [搜索]
- Android中Context的详细介绍
- 空气质量模型:操作指南与案例研究(模型概述)
- 如何设置ddns动态域名服务实现外网访问
- 随机森林+python代码实现
- 邮票问题(两张邮票)
- html表格制作旅游网页,简单实用的网页表格特效_html
- mysql数据库总是自动关闭_急求关于mysql数据库自动停止的问题
- 创新创意ssm计算机毕业设计题目300例之java农商行贷款管理系统f1gnk
- SQL创建某一年日历表
- Dave Oracle 学习 手册 第一版 下载 说明
- CSS3_01_圆角_边框_渐变_字体
- 【暑假复习】【搜索】POJ3009:Curling 2.0
- matlab 历史波动率,如何用Excel统计历史波动率
- unity 导出模型为fbx 格式