EventBus3.0 源码解析以及跨进程事件机制

本文详细解析了EventBus3.0的类定义、使用方式、核心属性、事件机制以及如何修改EventBus以支持多进程通讯。重点讨论了EventBus的注册、解注册和事件触发过程,特别是EventBus如何通过AnnnationProcessor提高性能,并介绍了如何利用AIDL实现多进程间的事件同步。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、类定义

  • 为了更好的说明问题,在介绍EventBus源码以及机制之前,我们先定义两个类:EventClass,SubscriberClass分别泛指用户自定义的事件类和事件的订阅者, eventObject, subscriberObject分别泛指订阅者和被订阅事件的实例。

EventClass

public class EventClass {
    private String message;
    public EventClass() {
    }
    public EventClass(String message) {
        this.message = message;
    }
    public String getMessage() {
        return message;
    }
    public void setMessage(String message) {
        this.message = message;
    }
}

复制代码

SubscriberClass

public class SubscriberClass {
    @Subscribe(threadMode = ThreadMode.MAIN,sticky = true)
    public void onMessageEvent(EventClass eventObject) {
        Log.e("MessageSubscriber", "onMessageEvent1:" + eventObject.getMessage());
    }

    @Subscribe(threadMode = ThreadMode.BACKGROUND, priority = 2,sticky = true)
    public void onMessageEvent3(EventClass eventObject) {
        Log.e("MessageSubscriber", "onMessageEvent3:" + eventObject.getMessage());
    }

    @Subscribe(threadMode = ThreadMode.BACKGROUND, priority = 10,sticky = true)
    public void onMessageEvent4(EventClass eventObject) {
        Log.e("MessageSubscriber", "onMessageEvent4:" + eventObject.getMessage());
    }

    @Subscribe(threadMode = ThreadMode.ASYNC, priority = 100,sticky = true)
    public void onMessageEvent5(EventClass eventObject) {
        Log.e("MessageSubscriber", "onMessageEvent5:" + eventObject.getMessage());
    }
}

复制代码

二、使用方式:

  • 订阅者注册,事件触发
1.注册订阅者:
SubscriberClass subscriberObject = new SubscriberClass();
EventBus.getDefault().register(subscriberObject);
复制代码
2.触发事件:
EventBus.getDefault().post(new EventClass("Hello World"));
复制代码
3.接收事件: 事件被post出后,就可以在subscriberObject对象的各个参数为EventClass方法中接收到了。可见subscriberObject在使用方法上非常像接口对象,等待被回调。

三、EventBus类:

  • 在我们了解EventBus的订阅,触发逻辑之前,我们先来了解一下EventBus
EventBus类中的关键属性:
private final Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType; 
private final Map<Object, List<Class<?>>> typesBySubscriber;
private final Map<Class<?>, Object> stickyEvents;
private final ThreadLocal<PostingThreadState> currentPostingThreadState;
private final SubscriberMethodFinder subscriberMethodFinder;
复制代码
1.subscriptionsByEventType
  • key:eventObject的Class;value:一个线程安全的Subscription列表。 我们先来了解一下Subscription类: Subscription

      final Object subscriber;    // 注册EventBus事件接收者的对象。即我们上面定义的subscribeObject;显然一个Subscription的粒度是订阅者对象级别,而不是类级别。
      final SubscriberMethod subscriberMethod; // 一个事件捕捉者的封装类对象
    复制代码

    SubscriberMethod

      final Method method;           // 捕捉事件的方法即 subcribeObject的某个参数类型为eventType的method
      final ThreadMode threadMode;  // 从方法注解中解析出的方法的相关描述信息:线程模型
      final Class<?> eventType;    // 方法的参数类型,即上文定义的eventObject的参数类。
      final int priority;         // 事件优先级
      final boolean sticky;      // 是否是stickEvent
      String methodString;      // 相当于一个方法的标签,用于比较是否相同
    复制代码

    由以上代码以及注释可见:Subscription是一个事件的执行单元。因此 EventBus的属性**subscriptionsByEventType**的作用非常关键,当post eventObject时,会根据eventObject的类型通过 subscriptionsByEventType.get(eventObject.getClass())获取到一个Subscription,使用Subscription通过反射调用subscribeObject的相关方法,从而使订阅者接收到事件。当然具体的调用过程略复杂,我们稍后讲解。

2.typesBySubscriber
  • key:观察者subscribeObject; value:subscribeObject类的所有被观察者(eventObject)的Class。 typesBySubscriber主要在unregist的过程中起作用(regist时生成和更新),unregist时,根据订阅者(subscribeObject)的类型(key),找到所有被订阅事件(eventObject)的类型List,根据事件类型在subscriptionsByEventType中找到所有观察者Subscriptions,如果Subscription的执行者是subscribeObject,则移除(因为显然一个Subscription是订阅者对象级别,而非类级别)。所以typesBySubscriber只起到记录作用。
3.stickyEvents
  • key:被观察者(事件)类型;value:被观察者(事件对象)。可见,相同的事件类型只会存储最近一次发送的事件。
4.currentPostingThreadState
  • 场景: 存储当前线程的事件发送状况。当post一个事件,如果当前线程正在post事件则会进入post事件池,否则while循环从事件池不断取出事件,调用postSingleEvent(Object event, PostingThreadState postingState)方法,找到所有订阅者类名。分别调用postSingleEventForEventType(Object event, PostingThreadState postingState, Class<?> eventClass)调用‘subscriptionsByEventType.get()’获取所有当前事件的Subscription,
    • **PostingThreadState**类:

      final static class PostingThreadState {
         final List<Object> eventQueue = new ArrayList<>();
         boolean isPosting;              // 当前线程是否正在发送事件
         boolean isMainThread;          // 当前线程是否是MainThread
         Subscription subscription;    // 正在发送的事件的正在发送给的订阅者;
         Object event;                // 被观察者,事件
         boolean canceled;           // 事件是否被取消了,事件一般会被更高优先级的事件取消。
      }
      复制代码
5.subscriberMethodFinder
  • SubscriberMethodFinder类对象 对外只提供了findSubscriberMethods方法。此类的作用是通过subscribeObject对象的类型,找到此类中所有的事件接收方法。封装成List。在EventBus类的逻辑用于生成和更新subscriptionsByEventTypetypesBySubscriber。具体组装逻辑在后面章节讲解,此类也是EventBus2.x和EventBus3.x的主要区别。
6.标记性属性:以下EventBus中的标记性属性比较简单
private final boolean throwSubscriberException;    // 在反射调用subscriberObject中的方法失败时是否抛出异常
private final boolean logSubscriberExceptions;    // 在反射调用subscriberObject中的方法失败时是否打印log
private final boolean logNoSubscriberMessages;        // post的eventObject无订阅者时是否打印log
private final boolean sendSubscriberExceptionEvent;  // 在反射调用subscriberObject中的方法失败时是否post出SubscriberExceptionEvent事件,用户可以像订阅普通事件一样订阅SubscriberExceptionEvent
private final boolean sendNoSubscriberEvent;  // post的eventObject无订阅者时是否post NoSubscriberEvent...
private final boolean eventInheritance;      // post的evntObject是否触发父类对象订阅者,默认为true
private final int indexCount;               // 注解生成类数量,没有实际用处。
private final Logger logger;
复制代码
7.当然还有各类事件执行器。
private final Poster mainThreadPoster;     // 实际是 AndroidHandlerMainThreadSupport实例,规定了Looper为MainThreadLooper的HandlerPoster
private final BackgroundPoster backgroundPoster;
private final AsyncPoster asyncPoster;
private final ExecutorService executorService;    
复制代码

根据subscribeObject--> Subscription--> SubscriberMethod--> Method 的注解,ThreadMode,分别使用不同方式在不同线程触发事件。这也是EventBus在各线程中进行穿插传递的原因。 并且AsyncPoster,BackgroundPoster,SubscriberPoster这些事件执行器都是在EventBusBuilder中初始化的Executors.newCachedThreadPool();

四、 EventBus3.0 事件机制

OK 分析完EventBus类中的基本属性之后,更详细的分析EventBus的事件机制,包括订阅者注册和事件触发两部分。

1.register源码分析:

EventBus3.0 订阅者注册的过程,实际为EventBus中的两个重要属性subscriptionsByEventType typesBySubscriber的组织构造过程。 EventBus3.0 之后提供了AnnnationProcessor机制,替换掉了一部分需要使用反射的地方(事件注册部分),大大提高了性能。但是在事件触发阶段依然会用到反射。


方案是为解决特定问题或达成特定目标而制定的一系列计划或步骤。它的作用是提供一种系统性的方法,以有效地应对挑战、优化流程或实现目标。以下是方案的主要作用: 问题解决: 方案的核心目标是解决问题。通过系统性的规划和执行,方案能够分析问题的根本原因,提供可行的解决方案,并引导实施过程,确保问题得到合理解决。 目标达成: 方案通常与明确的目标相关联,它提供了一种达成这些目标的计划。无论是企业战略、项目管理还是个人发展,方案的制定都有助于明确目标并提供达成目标的路径。 资源优化: 方案在设计时考虑了可用资源,以最大化其效用。通过明智的资源分配,方案可以在有限的资源条件下实现最大的效益,提高效率并减少浪费。 风险管理: 方案通常会对潜在的风险进行评估,并制定相应的风险管理策略。这有助于减轻潜在问题的影响,提高方案的可行性和可持续性。 决策支持: 方案提供了决策者所需的信息和数据,以便做出明智的决策。这种数据驱动的方法有助于减少不确定性,提高决策的准确性。 团队协作: 复杂的问题通常需要多个人的协同努力。方案提供了一个共同的框架,帮助团队成员理解各自的职责和任务,促进协作并确保整个团队朝着共同的目标努力。 监控与评估: 方案通常包括监控和评估的机制,以确保实施的有效性。通过定期的评估,可以及时调整方案,以适应变化的环境或新的挑战。 总体而言,方案的作用在于提供一种有序、有计划的方法,以解决问题、实现目标,并在实施过程中最大化资源利用和风险管理。 方案是为解决特定问题或达成特定目标而制定的一系列计划或步骤。它的作用是提供一种系统性的方法,以有效地应对挑战、优化流程或实现目标。以下是方案的主要作用: 问题解决: 方案的核心目标是解决问题。通过系统性的规划和执行,方案能够分析问题的根本原因,提供可行的解决方案,并引导实施过程,确保问题得到合理解决。 目标达成: 方案通常与明确的目标相关联,它提供了一种达成这些目标的计划。无论是企业战略、项目管理还是个人发展,方案的制定都有助于明确目标并提供达成目标的路径。 资源优化: 方案在设计时考虑了可用资源,以最大化其效用。通过明智的资源分配,方案可以在有限的资源条件下实现最大的效益,提高效率并减少浪费。 风险管理: 方案通常会对潜在的风险进行评估,并制定相应的风险管理策略。这有助于减轻潜在问题的影响,提高方案的可行性和可持续性。 决策支持: 方案提供了决策者所需的信息和数据,以便做出明智的决策。这种数据驱动的方法有助于减少不确定性,提高决策的准确性。 团队协作: 复杂的问题通常需要多个人的协同努力。方案提供了一个共同的框架,帮助团队成员理解各自的职责和任务,促进协作并确保整个团队朝着共同的目标努力。 监控与评估: 方案通常包括监控和评估的机制,以确保实施的有效性。通过定期的评估,可以及时调整方案,以适应变化的环境或新的挑战。 总体而言,方案的作用在于提供一种有序、有计划的方法,以解决问题、实现目标,并在实施过程中最大化资源利用和风险管理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值