Guava Eventbus-2

111 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第10天,点击查看活动详情

三、源码分析

1、初始化EvenBus

    EventBus(String identifier, Executor executor, Dispatcher dispatcher, SubscriberExceptionHandler exceptionHandler) {
        this.subscribers = new SubscriberRegistry(this);//所有观察者列表维护对象
        this.identifier = (String) Preconditions.checkNotNull(identifier);// EventBus的处理标识符(方法名称)
        //executor是事件分发过程中使用到的线程池,可以自己实现
        this.executor = (Executor)Preconditions.checkNotNull(executor);
        //Dispatcher类型的子类,对监听者分发策略,主要有3种方式
        this.dispatcher = (Dispatcher)Preconditions.checkNotNull(dispatcher);
        //异常处理策咯
        this.exceptionHandler = (SubscriberExceptionHandler)Preconditions.checkNotNull(exceptionHandler);
    }

2、注册监听–>register()

作用:初始化监听者类型与监听方法的集合subscribers,在发布事件场景由传入参数类型,匹配、并执行对应监听者方法

img

①获取指定监听者对应的全部观察者集合(一对多)

②获取对应**@Subscribe**观察者事件类型(即:方法参数类型)集合

③添加对应类型所有观察者到集合事件集合中(即:SubscriberRegistry对象维护的subscribers集合)

subscribers说明:

private final ConcurrentMap<Class<?>, CopyOnWriteArraySet<Subscriber>> subscribers = Maps.newConcurrentMap();

防止并发问题维护一个ConcurrentMap集合,Subscriber集合对应velue使用的是Java中的CopyOnWriteArraySet集合,

主要作用:1、避免监听重复事件 2、适用于读多写少的场景:只要register()才写入,基本都是查询

findAllSubscribers()说明

img

①获取注册监听对象所有包含**@Subscribe**的方法(如下图所示⤵️)

②通过反射获取对应方法、及监听参数类型

③放入当前初始化的EventBus对象里面,维护监听对象与监听方法的对应关系

image-20210902151925962

image-20210902152042527

首先从subscriberMethodsCache缓存中获取监听对象映射关系,如果缓存中不存在通过反射遍历所有包含**@Subscribe**的方法

3、发布事件–>post()

image-20210902153805060

①getSubscribers()方法获取该事件对应的全部观察者

②Dispatcher-分发事件策略

ImmediateDispatcher:直接在当前线程中遍历所有的观察者并进行事件分发

LegacyAsyncDispatcher:使用全局队列,先将观察者依次放入队列,再顺序从队列中取出观察者对象进行事件分发

PerThreadQueuedDispatcher(默认):使用线程相关队列,会先获取当前线程的观察者队列,并将传入的观察者列表传入到该队列中;判断当前线程是否正在进行分发操作,如果没有在进行分发操作,就通过遍历上述队列进行事件分发

最后无论使用哪个分发器,都会执行dispatchEvent()方法,通过反射(target、method、executor)多线程触发监听方法

image-20210902154440044

四、EventBus运行流程

img