美文网首页源码解析
EventBus源码解析(一)——获取EventBus对象

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

作者: 海晨忆 | 来源:发表于2018-03-07 09:53 被阅读8次

    个人博客: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并且只有一个参数

    简单用法

    第一步:依赖

    implementation 'org.greenrobot:eventbus:3.1.1'
    

    第二步:注册与反注册

    //注册,在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,获得是同一个对象

    相关文章

      网友评论

        本文标题:EventBus源码解析(一)——获取EventBus对象

        本文链接:https://www.haomeiwen.com/subject/svmlfftx.html