深扒 EventBus:getDefault

本文章已授权玉刚说微信公众号转载

上一篇:深扒 EventBus:解锁新姿势

看源码的目的

  • 避开使用的误区

  • 了解框架的实现原理

  • 借鉴里面使用的设计模式和思想

EventBus.getDefault

首先从最常用的 getDefault 方法开始分析,我们使用 EventBus 必须先调用这个方法

首先让我们先看一下方法上面的注释

Convenience singleton for apps using a process-wide EventBus instance
复制代码

方便的单例应用程序使用进程范围的EventBus实例
复制代码

一看注释就知道这个方法是什么,这个方法采用了单例设计模式中的懒汉式(没用到的时候不初始化,用的时候才初始化),这个方法体里面还使用了 synchronized 同步代码块,就连单例对象也被volatile关键字修饰,可想而知 EventBus 的懒汉单例已经处理了线程安全的问题

EventBusBuilder

EventBus.getDefault 最终还是会调用 EventBus 的无参构造函数

在这里我们发现了一个类 EventBusBuilder,光看类名早已看透了一切

看透归看透,源码还是要看一看,不然怎么继续写下去,先简单撸一遍源码

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() {}

    public EventBusBuilder logSubscriberExceptions(boolean logSubscriberExceptions) {
        this.logSubscriberExceptions = logSubscriberExceptions;
        return this;
    }

    public EventBusBuilder logNoSubscriberMessages(boolean logNoSubscriberMessages) {
        this.logNoSubscriberMessages = logNoSubscriberMessages;
        return this;
    }

    public EventBusBuilder sendSubscriberExceptionEvent(boolean sendSubscriberExceptionEvent) {
        this.sendSubscriberExceptionEvent = sendSubscriberExceptionEvent;
        return this;
    }

    public EventBusBuilder sendNoSubscriberEvent(boolean sendNoSubscriberEvent) {
        this.sendNoSubscriberEvent = sendNoSubscriberEvent;
        return this;
    }

    public EventBusBuilder throwSubscriberException(boolean throwSubscriberException) {
        this.throwSubscriberException = throwSubscriberException;
        return this;
    }

    public EventBusBuilder eventInheritance(boolean eventInheritance) {
        this.eventInheritance = eventInheritance;
        return this;
    }

    public EventBusBuilder executorService(ExecutorService executorService) {
        this.executorService = executorService;
        return this;
    }

    public EventBusBuilder skipMethodVerificationFor(Class<?> clazz) {
        if (skipMethodVerificationForClasses == null) {
            skipMethodVerificationForClasses = new ArrayList<>();
        }
        skipMethodVerificationForClasses.add(clazz);
        return this;
    }

    public EventBusBuilder ignoreGeneratedIndex(boolean ignoreGeneratedIndex) {
        this.ignoreGeneratedIndex = ignoreGeneratedIndex;
        return this;
    }

    public EventBusBuilder strictMethodVerification(boolean strictMethodVerification) {
        this.strictMethodVerification = strictMethodVerification;
        return this;
    }

    public EventBusBuilder addIndex(SubscriberInfoIndex index) {
        if (subscriberInfoIndexes == null) {
            subscriberInfoIndexes = new ArrayList<>();
        }
        subscriberInfoIndexes.add(index);
        return this;
    }

    public EventBusBuilder logger(Logger logger) {
        this.logger = logger;
        return this;
    }

    Logger getLogger() {
        if (logger != null) {
            return logger;
        } else {
            // also check main looper to see if we have "good" Android classes (not Stubs etc.)
            return Logger.AndroidLogger.isAndroidLogAvailable() && getAndroidMainLooperOrNull() != null
                    ? new Logger.AndroidLogger("EventBus") :
                    new Logger.SystemOutLogger();
        }
    }

    MainThreadSupport getMainThreadSupport() {
        if (mainThreadSupport != null) {
            return mainThreadSupport;
        } else if (Logger.AndroidLogger.isAndroidLogAvailable()) {
            Object looperOrNull = getAndroidMainLooperOrNull();
            return looperOrNull == null ? null :
                    new MainThreadSupport.AndroidHandlerMainThreadSupport((Looper) looperOrNull);
        } else {
            return null;
        }
    }

    Object getAndroidMainLooperOrNull() {
        try {
            return Looper.getMainLooper();
        } catch (RuntimeException e) {
            // Not really a functional Android (e.g. "Stub!" maven dependencies)
            return null;
        }
    }

    public EventBus installDefaultEventBus() {
        synchronized (EventBus.class) {
            if (EventBus.defaultInstance != null) {
                throw new EventBusException("Default instance already exists." +
                        " It may be only set once before it's used the first time to ensure consistent behavior.");
            }
            EventBus.defaultInstance = build();
            return EventBus.defaultInstance;
        }
    }

    public EventBus build() {
        return new EventBus(this);
    }
}
复制代码

这个类采用的是 Builder 建造者设计模式(简单来说就是将本体对象和参数设置进行分离),没错这个类就是对 EventBus 的参数配置

比如它的第一个字段就是用到了线程池:

上面这种写法很巧妙,默认的线程池对象是静态的,而对象中的线程池则引用了默认的,这样就能避免线程池的不必要的创建,如果对这种线程池的配置不满意还可以使用下面这个方法进行重新设置

最后在 build 方法创建 EventBus 对象,将自己 EventBusBuilder.this 作为参数

看到这里你是否明白了,EventBus 不止是可以通过 getDefault 方法获取一个 EventBus,也可以通过 EventBusBuilder 来创建一个 EventBus

但是如果我要把这个 EventBus 作为全局 EventBus 呢?该怎么办呢?让我们看看 installDefaultEventBus 方法源码

image.png

你会发现 installDefaultEventBus 最终还是会调用 build 方法,但是有一点需要注意的是,它把这个创建的 EventBus 对象设置为静态的,这样我们就可以通过 EventBus.getDefault() 获取到这个单例的 EventBus 对象

Android技术讨论Q群:78797078

猜你喜欢

转载自juejin.im/post/7053284256612614158