news 2026/4/27 8:41:07

EventBus源码主要流程解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
EventBus源码主要流程解析

首先从最基本的EventBus类的register()看实现逻辑:

1. 订阅事件

通过一个SubscriberMethodFinder类查找对应订阅的方法,然后进行订阅。

public void register(Object subscriber) { if (AndroidDependenciesDetector.isAndroidSDKAvailable() && !AndroidDependenciesDetector.areAndroidComponentsAvailable()) { // Crash if the user (developer) has not imported the Android compatibility library. throw new RuntimeException("It looks like you are using EventBus on Android, " + "make sure to add the \"eventbus\" Android library to your dependencies."); } Class<?> subscriberClass = subscriber.getClass(); List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass); synchronized (this) { for (SubscriberMethod subscriberMethod : subscriberMethods) { subscribe(subscriber, subscriberMethod); } } }

看下SubscriberMethodFinder类的findSubscriberMethods的实现。

可以看见实际上是通过Class进行反射,然后获取到对应的方法对象。

List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) { List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass); if (subscriberMethods != null) { return subscriberMethods; } if (ignoreGeneratedIndex) { subscriberMethods = findUsingReflection(subscriberClass); } else { subscriberMethods = findUsingInfo(subscriberClass); } if (subscriberMethods.isEmpty()) { throw new EventBusException("Subscriber " + subscriberClass + " and its super classes have no public methods with the @Subscribe annotation"); } else { METHOD_CACHE.put(subscriberClass, subscriberMethods); return subscriberMethods; } } private List<SubscriberMethod> findUsingReflection(Class<?> subscriberClass) { FindState findState = prepareFindState(); findState.initForSubscriber(subscriberClass); while (findState.clazz != null) { findUsingReflectionInSingleClass(findState); findState.moveToSuperclass(); } return getMethodsAndRelease(findState); } private List<SubscriberMethod> findUsingInfo(Class<?> subscriberClass) { FindState findState = prepareFindState(); findState.initForSubscriber(subscriberClass); while (findState.clazz != null) { findState.subscriberInfo = getSubscriberInfo(findState); if (findState.subscriberInfo != null) { SubscriberMethod[] array = findState.subscriberInfo.getSubscriberMethods(); for (SubscriberMethod subscriberMethod : array) { if (findState.checkAdd(subscriberMethod.method, subscriberMethod.eventType)) { findState.subscriberMethods.add(subscriberMethod); } } } else { findUsingReflectionInSingleClass(findState); } findState.moveToSuperclass(); } return getMethodsAndRelease(findState); }

然后重新回到订阅方法,可以看到是把刚刚订阅超找到的方法和订阅者添加到CopyOnWriteArrayList中。并且还有个关键结构叫subscriptionsByEventType,这个容器包含了事件类型和订阅者,可以理解为EventType容器包含N个eventType的订阅队列,一个订阅队列中有多个订阅方法。

private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) { Class<?> eventType = subscriberMethod.eventType; Subscription newSubscription = new Subscription(subscriber, subscriberMethod); CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType); if (subscriptions == null) { subscriptions = new CopyOnWriteArrayList<>(); subscriptionsByEventType.put(eventType, subscriptions); } else { if (subscriptions.contains(newSubscription)) { throw new EventBusException("Subscriber " + subscriber.getClass() + " already registered to event " + eventType); } } 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<>(); 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); } } }

2. 发送事件

这边可以看到先将事件提交到事件队列中,然后执行循环并取出队列第一个事件并执行postSingleEvent()。可以看见根据event的类去查找订阅的对象。

public void post(Object event) { PostingThreadState postingState = currentPostingThreadState.get(); List<Object> eventQueue = postingState.eventQueue; eventQueue.add(event); if (!postingState.isPosting) { postingState.isMainThread = isMainThread(); 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; } } } private void postSingleEvent(Object event, PostingThreadState postingState) throws Error { Class<?> eventClass = event.getClass(); boolean subscriptionFound = false; if (eventInheritance) { List<Class<?>> eventTypes = lookupAllEventTypes(eventClass); int countTypes = eventTypes.size(); for (int h = 0; h < countTypes; h++) { Class<?> clazz = eventTypes.get(h); subscriptionFound |= postSingleEventForEventType(event, postingState, clazz); } } else { subscriptionFound = postSingleEventForEventType(event, postingState, eventClass); } if (!subscriptionFound) { if (logNoSubscriberMessages) { logger.log(Level.FINE, "No subscribers registered for event " + eventClass); } if (sendNoSubscriberEvent && eventClass != NoSubscriberEvent.class && eventClass != SubscriberExceptionEvent.class) { post(new NoSubscriberEvent(this, event)); } } }

最后可以看见将事件作为参数,对订阅者的订阅方法进行了反射调用,这样就实现了事件分发功能。

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; 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; } private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) { switch (subscription.subscriberMethod.threadMode) { case POSTING: invokeSubscriber(subscription, event); break; case MAIN: if (isMainThread) { invokeSubscriber(subscription, event); } else { mainThreadPoster.enqueue(subscription, event); } break; case MAIN_ORDERED: if (mainThreadPoster != null) { mainThreadPoster.enqueue(subscription, event); } else { // temporary: technically not correct as poster not decoupled from subscriber invokeSubscriber(subscription, event); } break; case BACKGROUND: if (isMainThread) { 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); } }
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/27 8:41:07

游戏帧率优化大师指南:从基础配置到专业调优的完整路径

游戏帧率优化大师指南&#xff1a;从基础配置到专业调优的完整路径 【免费下载链接】genshin-fps-unlock unlocks the 60 fps cap 项目地址: https://gitcode.com/gh_mirrors/ge/genshin-fps-unlock 您是否在热门游戏中遭遇画面卡顿、操作延迟的困扰&#xff1f;当高性能…

作者头像 李华
网站建设 2026/4/23 7:05:40

36、探索CDF:网络频道订阅与管理全攻略

探索CDF:网络频道订阅与管理全攻略 1. 网络订阅的优势与工具对比 在网络浏览中,用户希望具备以下能力: - 更好地跟踪所订阅的网站。 - 当频道或收藏夹更新时接收通知。 - 在线或离线查看系统上的内容。 曾经,Netscape仅提供原始的手动网站/书签检查工具。虽然它最近开…

作者头像 李华
网站建设 2026/4/23 7:05:39

39、深入解析SOAP、UDDI与WSDL:构建Web服务通信基石

深入解析SOAP、UDDI与WSDL:构建Web服务通信基石 1. 引言 在当今的互联网世界中,Web服务的重要性日益凸显。而Simple Object Access Protocol(SOAP)作为一种用于在Web服务之间传递XML消息的流行协议,备受关注。但SOAP并非孤立存在,它是由Web Services Description Langu…

作者头像 李华
网站建设 2026/4/20 2:11:43

42、数学标记语言 MathML 全解析

数学标记语言 MathML 全解析 1. 数学表达式标记的发展与问题 从 20 世纪 80 年代至今,不少文字处理和图形应用程序具备了创建数学和科学表达式的能力,这些表达式通常会被转换为专有格式或图形格式(如 JPEG、GIF 或 TIFF)。然而,这些发展仅能实现视觉呈现,无法传达数学和…

作者头像 李华
网站建设 2026/4/23 6:44:36

5分钟学会:飞书文档批量导出完整指南

5分钟学会&#xff1a;飞书文档批量导出完整指南 【免费下载链接】feishu-doc-export 项目地址: https://gitcode.com/gh_mirrors/fe/feishu-doc-export 还在为飞书文档迁移而烦恼吗&#xff1f;feishu-doc-export工具帮你解决所有痛点&#xff0c;只需简单配置就能将飞…

作者头像 李华
网站建设 2026/4/23 7:05:04

Mermaid Live Editor 在线图表制作工具使用指南

Mermaid Live Editor 在线图表制作工具使用指南 【免费下载链接】mermaid-live-editor Location has moved to https://github.com/mermaid-js/mermaid-live-editor 项目地址: https://gitcode.com/gh_mirrors/mer/mermaid-live-editor 请基于以下要求撰写一篇关于 Merm…

作者头像 李华