EventBus3.0源码解析-第一篇

本文深入解析EventBus的工作原理,包括事件订阅、事件分发及不同线程模式下的事件处理流程,探讨其优缺点。

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

先介绍一下写这篇文章的背景,因为几乎每个项目中都使用到了EventBus,但是对它的理解仅仅在于如何使用,而不知其详细由来(当然以前还是知道个大概!),俗话说的好:“授人以鱼不如授人以渔”,今天让我这个老菜鸟来学习一下渔术!!!

什么是EventBus
EventBus翻译过来是事件总线的意思,官方对其描述由一张图即可说明其作用EventBus3.0是不是很清晰呢!
简单的翻译一下这张图,Subscriber订阅Event,并将Subscriber注册到事件总线(EventBus),Publisher发送Event并通过事件总线找到相应的Subscriber使其接收到相应Event。

EventBus的优点:
1.使用便捷:Subscriber只需定义public关键字的方法并已@Subscribe为注解即可订阅使用。
2.操作支持性强:通过@Subscribe可根据使用者的需要,定义ThreadMode、sticky、priority

EventBus的缺点:
.强引用:EventBus对Subscriber使用的是强引用,不再使用时需unRegister Subscriber
.订阅的事件多了以后会导致EventClass很多,使其比较难管理
.多个Subscriber订阅相同的Event,如果在主线程订阅的,处理不当可能会造成耗时严重时导致ANR

EventBus源码分析

1.EventBus初始化时做了什么
2.如何订阅
3.发送事件的时候做了什么

.EventBus初始化时做了什么

EventBus.getDefault()

//点进去查看源码

/** Convenience singleton for apps using a process-wide EventBus instance. */
public static EventBus getDefault() {
   
        if (defaultInstance == null) {
   
            synchronized (EventBus.class) {
   
                if (defaultInstance == null) {
   
                    defaultInstance = new EventBus();
                }
            }
        }
        return defaultInstance;
}

EventBus.getDefault() 方法创建了一个实例,我们看看里面配置了哪些参数

    ...省略代码
    private static final EventBusBuilder DEFAULT_BUILDER = new EventBusBuilder();
    ...省略代码
    /**
     * Creates a new EventBus instance; each instance is a separate scope in which events are delivered. To use a
     * central bus, consider {@link #getDefault()}.
     */
    public EventBus() {
   
        this(DEFAULT_BUILDER);
    }

    EventBus(EventBusBuilder builder) {
   
        logger = builder.getLogger();
        subscriptionsByEventType = new HashMap<>();
        typesBySubscriber = new HashMap<>();
        stickyEvents = new ConcurrentHashMap<>();
        mainThreadSupport = builder.getMainThreadSupport();//内部逻辑是得到主线程的looper
        mainThreadPoster = mainThreadSupport != null ? mainThreadSupport.createPoster(this) : null;//main poster
        backgroundPoster = new BackgroundPoster(this);//backgroundPoster
        asyncPoster = new AsyncPoster(this);//异步Poster
        indexCount = builder.subscriberInfoIndexes != null ? builder.subscriberInfoIndexes.size() : 0;
        subscriberMethodFinder = new SubscriberMethodFinder(builder.subscriberInfoIndexes,
                builder.strictMethodVerification, builder.ignoreGeneratedIndex);//通过这个实例查找当前的订阅者订阅了哪些时间并为之存起来
        logSubscriberExceptions = builder.logSubscriberExceptions;
        logNoSubscriberMessages = builder.logNoSubscriberMessages;
        sendSubscriberExceptionEvent = builder.sendSubscriberExceptionEvent;
        sendNoSubscriberEvent = builder.sendNoSubscriberEvent;
        throwSubscriberException = builder.throwSubscriberException;
        eventInheritance = builder.eventInheritance;
        executorService = builder.executorService;//内部创建了线程池,根据Subscriber订阅的Event的ThreadMode来执行哪一种Poster
    }

EventBus通过建造者模式初始化的我们看看EventBusBuilder里面是怎么设置的

/**
 * Creates EventBus instances with custom parameters and also allows to install a custom default EventBus instance.
 * Create a new builder using {@link EventBus#builder()}.
 */
public class EventBusBuilder {
   
    private final static ExecutorService DEFAULT_EXECUTOR_SERVICE = Executors.newCachedThreadPool();//创建了一个线程池

    boolean logSubscriberExceptions = true;
    boolean logNoSubscriberMessages = true;
    boolean sendSubscriberExceptionEvent = true;
    boolean sendNoSubscriberEvent = true;
    boolean throwSubscriberException;
    boolean eventInheritance = true;
    boolean ignoreGeneratedIndex;
    boolean strictMethodVerification;
    ExecutorService executorService = DEFAULT_EXECUTOR_SERVICE;
    List<Class<?>> skipMethodVerificationForClasses;
    List<SubscriberInfoIndex> subscriberInfoIndexes;
    Logger logger;
    MainThreadSupport mainThreadSupport;

    EventBusBuilder() {
   
    }
    ...省略代码

.如何订阅
接下来我们分析分析EventBus.register(Object subscriber) 方法里都做了什么

    public void register(Object subscriber) {
   
        Class<?> subscriberClass = subscriber.getClass();
        List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);//查找订阅者订阅的事件(Method)
        synchronized (this) {
   
            for (SubscriberMethod subscriberMethod : subscriberMethods) {
   
                subscribe(subscriber, subscriberMethod);//处理订阅
            }
        }
    }

看看subscriberMethodFinder这个对象在创建EventBus时就初始化了 subscriberMethodFinder.findSubscriberMethods(Class<?> subscriberClass) 方法里面做了什么呢,直接拉出整段代码

class SubscriberMethodFinder {
   
     ...省略代码
    SubscriberMethodFinder(List<SubscriberInfoIndex> subscriberInfoIndexes, boolean strictMethodVerification,
                           boolean ignoreGeneratedIndex) {
   
        this.subscriberInfoIndexes = subscriberInfoIndexes;
        this.strictMethodVerification = strictMethodVerification;
        this.ignoreGeneratedIndex = ignoreGeneratedIndex;
    }

    List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
   
        List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);//先去缓存里面拿,最开始肯定是为空的,因为还没有存,所有接着往下走
        if (subscriberMethods != null) {
   //在缓存中拿大,返回订阅者订阅的方法
            return subscriberMethods;
        }

        if (ignoreGeneratedIndex) {
   //ignoreGeneratedIndex默认为false
            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"
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值