news 2026/6/10 2:21:47

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/6/10 11:11:47

29、VML 技术全面解析:从基础到应用

VML 技术全面解析:从基础到应用 1. VML 概述 VML(Vector Markup Language)具有多方面优势,部分源于其矢量图形特性,部分得益于与 Microsoft Internet Explorer 的关联: - 文件传输快 :矢量图形文件通常较小,传输速度比位图图像更快。 - 易于创建和更新 :VML 文…

作者头像 李华
网站建设 2026/6/10 3:16:33

30、可缩放矢量图形(SVG)与VML、SMIL技术解析

可缩放矢量图形(SVG)与VML、SMIL技术解析 1. 可缩放矢量图形(SVG)概述 1998年,除了VML,W3C还收到了另外三项与矢量图形相关的提案: - 精密图形标记语言(1998年3月)。 - 万维网网络示意图,由研究理事会中央实验室理事会代表于1998年3月提交的提案(W3C也给予了注释…

作者头像 李华
网站建设 2026/6/9 21:08:37

如何免费整理Windows桌面:终极桌面管理工具NoFences指南

如何免费整理Windows桌面&#xff1a;终极桌面管理工具NoFences指南 【免费下载链接】NoFences &#x1f6a7; Open Source Stardock Fences alternative 项目地址: https://gitcode.com/gh_mirrors/no/NoFences 在数字化时代&#xff0c;我们的Windows桌面往往被各种图…

作者头像 李华
网站建设 2026/6/10 11:07:25

Vue 3 + Element Plus MessageBox 从基础应用到高级架构实践

文章目录概述一、 核心概念&#xff1a;为什么选择 MessageBox&#xff1f;1. 命令式 vs. 声明式2. 基础调用与响应式集成1.安装与引入&#xff08;保持不变&#xff09;2.在 Composition API 中的响应式实践二、 进阶实践&#xff1a;驾驭复杂场景与自定义1. 动态内容与 VNode…

作者头像 李华
网站建设 2026/6/10 5:16:13

iStore插件中心完整使用手册:让OpenWRT插件管理变得简单高效

iStore插件中心完整使用手册&#xff1a;让OpenWRT插件管理变得简单高效 【免费下载链接】istore 一个 Openwrt 标准的软件中心&#xff0c;纯脚本实现&#xff0c;只依赖Openwrt标准组件。支持其它固件开发者集成到自己的固件里面。更方便入门用户搜索安装插件。The iStore is…

作者头像 李华
网站建设 2026/6/10 11:08:39

如何快速掌握NotepadNext十六进制编辑:面向初学者的终极指南

如何快速掌握NotepadNext十六进制编辑&#xff1a;面向初学者的终极指南 【免费下载链接】NotepadNext A cross-platform, reimplementation of Notepad 项目地址: https://gitcode.com/GitHub_Trending/no/NotepadNext NotepadNext作为一款跨平台的文本编辑器&#xff…

作者头像 李华