天天看点

EventBus源码解析(一)——获取EventBus对象

个人博客:haichenyi.com。感谢关注

简介

我们先来看一下他的类注释

/**
 * EventBus is a central publish/subscribe event system for Android. Events are posted ({@link #post(Object)}) to the
 * bus, which delivers it to subscribers that have a matching handler method for the event type. To receive events,
 * subscribers must register themselves to the bus using {@link #register(Object)}. Once registered, subscribers
 * receive events until {@link #unregister(Object)} is called. Event handling methods must be annotated by
 * {@link Subscribe}, must be public, return nothing (void), and have exactly one parameter
 * (the event).
 *
 * @author Markus Junginger, greenrobot
 */
           

  英语不是很好,大致讲一下这段话是什么意思:EventBus是重要的发布/订阅的Android事件系统。事件被发布给总线,这个总线将这个事件传递给跟他匹配类型的订阅者。接收事件必须在总线使用的时候注册他们。一旦注册,订阅者就会一直接收事件,直到他们被取消注册。这个接收方法必须增加注解Subscribe标识,必须是public,返回类型是void,并且只有一个参数。 简单的来说,就是用之前必须先注册,然后接收方法必须有Subscribe注解,必须是public,返回类型是void并且只有一个参数

简单用法

第一步:依赖

第二步:注册与反注册

//注册,在onCrate里面
EventBus.getDefault().register(this)
//反注册,在onDestory里面
EventBus.getDefault().unregister(this)
           

第三步:接收方法

@Subscribe
public void handle(MyClothes myClothes){
    //你的具体逻辑
}
           

第四步:发送

EventBus.getDefault().post(new MyClothes())
           

  经过上面三步,你就可以正常使用EventBus了,前面两步要在一个类里面,因为接收之前,必须要注册,可以在任意的地方post

源码解析—getDefault()

public static EventBus getDefault() {
        if (defaultInstance == null) {
            synchronized (EventBus.class) {
                if (defaultInstance == null) {
                    defaultInstance = new EventBus();
                }
            }
        }
        return defaultInstance;
    }
           

  可以看到这里使用的是双重校验锁的单例模式,保证不同的线程调用该方法得到的都是同一个EventBus实例。

EventBus()

看到上面的单例模式之后,我们再来瞅瞅单例模式里面调用的构造方法

public EventBus() {
        this(DEFAULT_BUILDER);
    }
           

这里他的空参数的构造方法里面调用的是一个参数的构造方法,我们来看看这个参数是什么?

private static final EventBusBuilder DEFAULT_BUILDER = new EventBusBuilder();
           

EventBusBuilder()

EventBusBuilder() {
    }
           

这个builder的构造方法里面什么都没有,也就是说没有初始化任何变量,那我们看一看他的变量,这里我就说一个:

private final static ExecutorService DEFAULT_EXECUTOR_SERVICE = Executors.newCachedThreadPool();

ExecutorService executorService = DEFAULT_EXECUTOR_SERVICE;
           

Executors.newCachedThreadPool() 创建的是一个可缓存的线程池,如果线程池长度超过处理需要,可灵活回收空线程池,若无回收,可新建线程。

接下来,我们再来看看只有EventBusBuilder参数的构造方法

EventBus(EventBusBuilder builder)

EventBus(EventBusBuilder builder) {
        subscriptionsByEventType = new HashMap<>();
        typesBySubscriber = new HashMap<>();
        stickyEvents = new ConcurrentHashMap<>();
        mainThreadPoster = mainThreadSupport != null ? mainThreadSupport.createPoster(this) : null;
        backgroundPoster = new BackgroundPoster(this);
        asyncPoster = new AsyncPoster(this);
        ...
    }
           

  讲到这里,很明显,他这里用的是建造者模式,跟我们之前讲的Luban的模式是一样的,这个建造者模式,我就不讲了。讲Luban的时候讲过的

  这里我列出来的6个变量,其他变量并没有列出来,因为,其他变量都是builder里面的赋值,没有啥好讲的。我们来看看这6个成员变量的类型

private final Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType;
private final Map<Object, List<Class<?>>> typesBySubscriber;
private final Map<Class<?>, Object> stickyEvents;
private final Poster mainThreadPoster;
private final BackgroundPoster backgroundPoster;
private final AsyncPoster asyncPoster;
           

意义:

  1. subscriptionsByEventType:可以看到这是一个是以event的class为key,以subscribe的list为value的map,有的人可能不知道CopyOnWriteArrayList,这是ArrayList的一个线程安全变种。(这里,有人会点到Subscription里面去看一下,可以看到就是一个类,封装了订阅者和订阅方法,重写了hashcode和equal方法)
  2. typesBySubscriber:这是以订阅者类为key,以event的list为value的map,在注册和反注册的时候用的到
  3. stickyEvents:粘性事件,以event的class为key,订阅者为value的map
  4. 后面这三个Poster都是用来处理粘性事件的

  我们说了这么多成员变量。我们知道这里的EventBusBuilder就是给EventBus初始化成员变量的,辣么,我们可不可以不用getDefault,获取eventBus对象呢?

EventBus build1 = EventBus.getDefault();

EventBus build2 = EventBus.builder().build();
           

这两个build的区别是什么呢?我们可以点到build()方法里面去看一下:

public EventBus build() {
        return new EventBus(this);
    }
           

他这里是直接new出来的,并没有单例,所以每次使用的都是new一个新的对象,而通过getDefault,获得是同一个对象

继续阅读