android开源框架分析系列之-EventBus

最近在看开源框架,对于经常使用的EventBus,觉得用起来非常简单,所以比较好奇,看了几篇文章。然后把EventBus的关键点提取到了Anki上,随着时间的推移,突然发现印象越来越模糊,反反复复的看光是看理论印象还是不够深刻。于是,打算深挖一下EventBus的源码。

开篇习惯,带着问题看源码,如果你能回答出如下问题,那么,出门右转,不要浪费宝贵的大好青春~
1.简单的描述一个EventBus的使用Demo?
2.EventBus的注册是怎么回事?
3.当我使用PostEvent发送事件之后,EventBus会执行哪些流程?它是如何找到对应的事件的?
4.EventBus的取消注册是怎么回事?
5.简单的说一下粘性事件?

#关于EventBus

EventBus的简介,网上有的是,这里不再赘述,你只要知道,它使用的是观察者模式,通过Event来传递。

#带着问题看源码

##简单的描述一个EventBus的使用Demo?

###注册

EventBus.getDefault().register(this);

###自定义事件

public class MessageEvent{
    private String message;
    public  MessageEvent(String message){
        this.message=message;
    }
    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

###发送

EventBus.getDefault().post(messageEvent);

###处理事件

@Subscribe(threadMode = ThreadMode.MAIN)
public void XXX(MessageEvent messageEvent) {
    ...
}

###取消注册

EventBus.getDefault().unRegister(this);

##EventBus的注册是怎么回事?

接下来就带你看看注册的源码是怎么回事,先回忆一下上一节的代码,我们就使用了一句简单的EventBus.getDefault().register(this);就完成了注册,它主要分为两个部分:getDefault()和register(this);

那么getDefault是什么呢?
查看源代码得知,原来它就是一个使用了volatile和synchronized双重锁单例:

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

这里面还有一个小技巧:
/**
 * 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);
}

public static EventBusBuilder builder() {
    return new EventBusBuilder();
}
发现没,它是在单例的EventBus里面,默认设置了一个EventBusBuilder,通过EventBusBuilder的名字你大概能轻易的猜出来使用了构建者模式,最终返回的这个真正的EventBus。

在得到单例之后,就进行了注册:

下面就是注册方法:
注册的时候要注意,首先使用注册就一定要使用反注册,否则,你将会一直收到该消息;然后是一定要为处理该消息的方法进行声明,Subscribe也行,或者是再加上ThreadMode和优先级;

    public void register(Object subscriber) {
        Class<?> subscriberClass = subscriber.getClass();
        List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
        synchronized (this) {
            for (SubscriberMethod subscriberMethod : subscriberMethods) {
                subscribe(subscriber, subscriberMethod);
            }
        }
    }

注册主要分为两步:
###获取到注册类的所有的声明了Subscribe注解的事件:
注册的时候,会获取你注册的类对象,然后调用findSubscriberMethods方法,返回List集合,我们叫做观察者集合(我自己起的名)。
这里面用到了一个METHOD_CACHE,它是一个ConcurrentHashMap,考考你:什么是ConcurrentHashMap?它是如何使用size()方法如何容器大小的?

List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {

        List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);
        //这个地方就是一个设计模式:享元
        if (subscriberMethods != null) {
            return subscriberMethods;
        }

        if (ignoreGeneratedIndex) {
            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");
        } else {
            METHOD_CACHE.put(subscriberClass, subscriberMethods);
            return subscriberMethods;
        }
    }

然后接下来就是findUsingReflection

#参考文章
https://www.jianshu.com/p/f9ae5691e1bb