EventBus 源码解析

EventBus 源码解析

看个大图:
在这里插入图片描述

再来一个:
在这里插入图片描述

使用起来比较简单

EventBus.getDefault().register(Object);

EventBus.getDefault().unregister(Object);

EventBus.getDefault().post(Object);

@Subscribe(threadMode=ThreadMode.MAIN)
public void event(Object){
    //do something
}

注册、解注册、发送事件、接收事件,这个是普通用法;此外他还有黏性事件sticky

EventBus.getDefault().postSticky(Object);

@Subscribe(threadMode=ThreadMode.MAIN,,sticky =true)
public void event(Object){
    //do something
}

注册、解注册都是一样的,发送黏性事件,接收黏性事件;此外还有事件优先级priority;

@Subscribe(threadMode=ThreadMode.MAIN,,sticky =true,priority=0)
public void event(Object){
    //do something
}

按照优先级顺序进行事件接收,此外还有线程调度;

public enum ThreadMode {
    POSTING,
    MAIN,
    MAIN_ORDERED,
    BACKGROUND,
    ASYNC
}

五种线程调度方式:默认线程、主线程、主线程(排队)、非主线程、开辟一个新线程,在这里面执行;

还有最后一个,订阅方法索引;SubscriberInfoIndex;默认有索引开启,在索引中寻找要快速,否则就是反射去寻找,效率稍微低一点;

大部分就是这些用法,现在来看源码。

先约定几个词语:
订阅一方,为订阅者;
发送的事件,为事件(有事件类型,事件对象);
订阅的方法,为订阅方法(Subscribe方法经过包装为SubscriberMethod);
Subscription,为类订阅方法(订阅者和订阅方法的结合体);
PendingPost,为发送中事件(pending:正在进行中的这么一种状态);
SubscriberMethodFinder,为订阅搜寻者(寻找订阅方法);

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

他是个单例模式,使用的是double check;判断defaultInstance是否为null,是的话则加锁初始化,防止多次实例化;

static volatile EventBus defaultInstance;

volatile用在多线程同步变量时,线程为了提高效率,将某成员变量(如A)拷贝了一份(如B),线程中对A的访问其实访问的是B。只在某些动作时才进行A和B的同步。因此存在A和B不一致的情况。volatile就是用来避免这种情况的。volatile告诉jvm, 它所修饰的变量不保留拷贝,直接访问主内存中的(也就是上面说的A)

java中关键字volatile

public EventBus() {
    this(DEFAULT_BUILDER);
}

默认调用了无参构造方法EventBus;

private static final EventBusBuilder DEFAULT_BUILDER = new EventBusBuilder();
EventBus(EventBusBuilder builder) {
    logger = builder.getLogger();
    subscriptionsByEventType = new HashMap<>();
    typesBySubscriber = new HashMap<>();
    stickyEvents = new ConcurrentHashMap<>();
    mainThreadSupport = builder.getMainThreadSupport();
    mainThreadPoster = mainThreadSupport != null ? mainThreadSupport.createPoster(this) : null;
    backgroundPoster = new BackgroundPoster(this);
    asyncPoster = new AsyncPoster(this);
    indexCount = builder.subscriberInfoIndexes != null ? builder.subscriberInfoIndexes.size() : 0;
    subscriberMethodFinder = new SubscriberMethodFinder(builder.subscriberInfoIndexes,
                builder.strictMethodVerification, builder.ignoreGeneratedIndex);
    logSubscriberExceptions = builder.logSubscriberExceptions;
    logNoSubscriberMessages = builder.logNoSubscriberMessages;
    sendSubscriberExceptionEvent = builder.sendSubscriberExceptionEvent;
    sendNoSubscriberEvent = builder.sendNoSubscriberEvent;
    throwSubscriberException = builder.throwSubscriberException;
    eventInheritance = builder.eventInheritance;
    executorService = builder.executorService;
}

间接调用有参构造方法EventBus(EventBusBuilder builder);
里面主要是进行赋值,因为是默认调用,所以来看看默认参数:

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;
    ......
}

可以看出

//log
boolean logSubscriberExceptions = true;
boolean logNoSubscriberMessages = true;
//发送订阅异常事件
boolean sendSubscriberExceptionEvent = true;
//发送非订阅事件
boolean sendNoSubscriberEvent = true;
//是否抛出订阅异常
boolean throwSubscriberException;
//事件是否具有继承性(啥叫继承性?通俗来说就是找爸爸,不停的找超类/接口)
boolean eventInheritance = true;

这几个默认值改为了true;

开始注册:

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

传进来一个订阅者subscriber,获取他的类Class;
拿到当前订阅者(约定语)所有的订阅方法(约定语),拿到所有的订阅方法之后就开始循环订阅;

先来看看他是怎么拿到所有的订阅方法的:

List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);

这里面有五个东西:
SubscriberMethod:订阅方法(约定语);
subscriberMethods:订阅方法的集合;
subscriberMethodFinder:订阅搜寻者(约定语);
findSubscriberMethods:寻找订阅方法;
subscriberClass:事件Class;

先看一下SubscriberMethod

public SubscriberMethod(Method method, Class<?> eventType, ThreadMode threadMode, int priority, boolean sticky) {
    this.method = method;
    this.threadMode = threadMode;
    this.eventType = eventType;
    this.priority = priority;
    this.sticky = sticky;
}

看一下构造方法:Subscribe标注的方法、线程、事件类型、优先级、是否是黏性事件;一个订阅方法具有以上几个特征;

subscriberMethodFinder这个就先不说,会随着findSubscriberMethods方法会全部展开;

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;
    }
}

METHOD_CACHE:可以看得很明白,是一个Map,以订阅者Class作为Key,订阅者中的所有订阅方法的集合作为Value;

根据传进来的订阅者Class,找到所有的订阅方法的集合;

找到就直接返回,没找到就继续;

判断是否忽略索引,默认是false(为什么是默认false?因为这个值是subscriberMethodFinder构造的是否传进来的,初始化它的时候里面的值是从EventBusBuilder中传进来的,builder中没有做处理,所以默认false);判断这个,来用不同的方法来寻找;如果找到的订阅方法的集合是空,那就是你的不对了,你订阅了就一定要有订阅方法;找到之后不为空就放到METHOD_CACHE中,并返回找到的订阅方法的集合;

现在来看看那两个寻找方法:

subscriberMethods = findUsingReflection(subscriberClass);
private List<SubscriberMethod> findUsingReflection(Class<?> subscriberClass) {
        FindState findState = prepareFindState();
        findState.initForSubscriber(subscriberClass);
        while (findState.clazz != null) {
            findUsingReflectionInSingleClass(findState);
            findState.moveToSuperclass();
        }
        return getMethodsAndRelease(findState);
    }

FindState:可以看成是一个中间产物,在寻找的过程中记录过程中的一些状态值;他是SubscriberMethodFinder的静态内部类;

//订阅方法的集合
final List<SubscriberMethod> subscriberMethods = new ArrayList<>();
//事件类型做Key,Subscribe标记的方法做Value;目前我理解的是用作标签
final Map<Class, Object> anyMethodByEventType = new HashMap<>();
//这里面涉及到了一个MethodKey,他的组成比较特殊,比如一个方法event(com.xxx.bean.UserBean userBean),他就等于event>com.xxx.bean.UserBean;用这个MethodKey做Key,订阅者Class用作Value;
final Map<String, Class> subscriberClassByMethodKey = new HashMap<>();
//这个就是MethodKey
final StringBuilder methodKeyBuilder = new StringBuilder(128);
//订阅者Class
Class<?> subscriberClass;
//开始是订阅者Class,如果往超类追寻,他又指向超类Class
Class<?> clazz;
//是否跳过追寻父类
boolean skipSuperClasses;
//订阅者信息
SubscriberInfo subscriberInfo;

以上是FindState中的属性,也就是会产生的中间状态值;

private static final int POOL_SIZE = 4;
private static final FindState[] FIND_STATE_POOL = new FindState[POOL_SIZE];

private FindState prepareFindState() {
    synchronized (FIND_STATE_POOL) {
        for (int i = 0; i < POOL_SIZE; i++) {
            FindState state = FIND_STATE_POOL[i];
            if (state != null) {
                FIND_STATE_POOL[i] = null;
                return state;
            }
        }
    }
    return new FindState();
}

这里维持了一个状态池,大小为4;每次都去状态池中寻找空闲的对象,找到不为空的就拿出来返回,并将当前位置置空,找不到就新建一个返回;

void initForSubscriber(Class<?> subscriberClass) {
    this.subscriberClass = clazz = subscriberClass;
    skipSuperClasses = false;
    subscriberInfo = null;
}

初始化,subscriberClass和clazz一开始都指向订阅者Class;skipSuperClasses设置为默认不跳过超类,订阅者信息默认为null;

while (findState.clazz != null) {
    findUsingReflectionInSingleClass(findState);
    findState.moveToSuperclass();
}

看到这个while循环就知道,这块代码可能要纠缠一会儿了,磨人的小妖精;

//先大概说一下这段代码是干啥的:拿到当前类中的所有订阅方法,然后检查判断是否添加到中间状态的订阅方法集合中;
private void findUsingReflectionInSingleClass(FindState findState) {
    //定义一个方法数组
    Method[] methods;
    try {
        // This is faster than getMethods, especially when subscribers are fat classes like Activities
        //拿到当前订阅者Class的所有方法
        methods = findState.clazz.getDeclaredMethods();
    } catch (Throwable th) {
            // Workaround for java.lang.NoClassDefFoundError, see https://github.com/greenrobot/EventBus/issues/149
        //拿到当前订阅者的所有public方法
        methods = findState.clazz.getMethods();
        //跳过追寻父类
        findState.skipSuperClasses = true;
    }
    //遍历所有找到的方法
    for (Method method : methods) {
        //获取修饰符
        int modifiers = method.getModifiers();
        //做条件阻拦,只允许public方法;A&B操作,如果A==B,则A&B==0;
        //private static final int MODIFIERS_IGNORE = Modifier.ABSTRACT | Modifier.STATIC | BRIDGE | SYNTHETIC;MODIFIERS_IGNORE是抽象、静态、桥接方法<啥叫桥接,下面我放了一个链接,自己看看>、SYNTHETIC
        if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) {
            //获取参数类型的个数,就是看你有几个参数
            Class<?>[] parameterTypes = method.getParameterTypes();
            //筛选出只有一个参数的,先干掉一批
            if (parameterTypes.length == 1) {
                //去获取方法上的注解Subscribe
                Subscribe subscribeAnnotation = method.getAnnotation(Subscribe.class);
                //能获取的到,能获取的到,才是我们的订阅方法,又干掉一批
                if (subscribeAnnotation != null) {
                    //获取参数类型
                    Class<?> eventType = parameterTypes[0];
                    //检查是否可以添加到临时状态的订阅方法集合中
                    if (findState.checkAdd(method, eventType)) {
                        //获取指定线程
                        ThreadMode threadMode = subscribeAnnotation.threadMode();
                        //组装SubscriberMethod,并添加到临时状态的订阅方法集合中
                        findState.subscriberMethods.add(new SubscriberMethod(method, eventType, threadMode,subscribeAnnotation.priority(), subscribeAnnotation.sticky()));
                    }
                }
            } else if (strictMethodVerification && method.isAnnotationPresent(Subscribe.class)) {
                //订阅方法只能有一个参数
                String methodName = method.getDeclaringClass().getName() + "." + method.getName();
                throw new EventBusException("@Subscribe method " + methodName +
                        "must have exactly 1 parameter but has " + parameterTypes.length);
            }
        } else if (strictMethodVerification && method.isAnnotationPresent(Subscribe.class)) {
            //订阅方法只能是public的普通方法
            String methodName = method.getDeclaringClass().getName() + "." + method.getName();
            throw new EventBusException(methodName +
                    " is a illegal @Subscribe method: must be public, non-static, and non-abstract");
        }
    }
}

Java反射中method.isBridge() 桥接方法
Java中的synthetic

具体的都在代码中的注释中细说了一遍,再来看看,他是如何检查是否可以添加到订阅方法集合中的?

if (findState.checkAdd(method, eventType)) {
    ThreadMode threadMode = subscribeAnnotation.threadMode();
    findState.subscriberMethods.add(new SubscriberMethod(method, eventType, threadMode,
            subscribeAnnotation.priority(), subscribeAnnotation.sticky()));
}

里面的代码比较好理解,就看看条件代码:

findState.checkAdd(method, eventType)
boolean checkAdd(Method method, Class<?> eventType) {
    // 2 level check: 1st level with event type only (fast), 2nd level with complete signature when required.
    // Usually a subscriber doesn't have methods listening to the same event type.
    //判断该参数类型的方法是否已经添加过
    Object existing = anyMethodByEventType.put(eventType, method);
    if (existing == null) {
        //已经添加过了就好说,没纷争
        return true;
    } else {
        //添加过了,事就被挑起来了
        if (existing instanceof Method) {
            //如果Value是Method类型,一般情况下都是,那就检查方法签名
            if (!checkAddWithMethodSignature((Method) existing, eventType)) {
                // Paranoia check
                throw new IllegalStateException();
            }
            // Put any non-Method object to "consume" the existing Method
            anyMethodByEventType.put(eventType, this);
        }
        //检查方法签名
        return checkAddWithMethodSignature(method, eventType);
    }
}

private boolean checkAddWithMethodSignature(Method method, Class<?> eventType) {
    //还记得这个特殊的MethodKey吧,看看他是怎么组成的,方法名+">"+参数名,如果方法名和参数名你都重了,那你就真重了;
    methodKeyBuilder.setLength(0);
    methodKeyBuilder.append(method.getName());
    methodKeyBuilder.append('>').append(eventType.getName());

    String methodKey = methodKeyBuilder.toString();
    //获取方法所属类的Class
    Class<?> methodClass = method.getDeclaringClass();
    //拿到重的前一个方法的类Class
    Class<?> methodClassOld = subscriberClassByMethodKey.put(methodKey, methodClass);
    //methodClassOld==null说明是第一次添加进来;不是第一次添加进来就看第二个条件;
    //如果methodClassOld是覆盖他的本身或者父类才能成立
    if (methodClassOld == null || methodClassOld.isAssignableFrom(methodClass)) {
        // Only add if not already found in a sub class
        return true;
    } else {
        // Revert the put, old class is further down the class hierarchy
        subscriberClassByMethodKey.put(methodKey, methodClassOld);
        return false;
    }
}

Java中isAssignableFrom的用法
这两个方法连着看比较好;

anyMethodByEventType之前说过这么个玩意,用参数Class作为Key,用注解标记的方法作为Value;

map的put方法有一个地方要关注一下:当再次put的可以在map中已经存在时返回上一个相同key的value,如果是第一次put进去,则返回null;

如果existing==null说明没有纷争,直接返回true,表示可以添加到List中;否则就要搞事情

判断存在返回的Value是否是Method类型,为什么这么搞,是为了做一个标签,正常情况下

Object existing = anyMethodByEventType.put(eventType, method);

可以看得出,这肯定是一个Method类型的Value,但是有一个意外:

anyMethodByEventType.put(eventType, this);

这个this是什么呢?是当前类SubscriberMethodFinder的对象;这就不是Method类型了;可以看出checkAddWithMethodSignature被调用了两次,如果有了这个标识,则只需要调用一次;

这里先打断一下,按照我们使用的逻辑,在一个订阅者中,是不应该存在参数相同的订阅方法的(方法名可以不同),这样做我真的想象不出来有何特殊作用;那何时会到else中呢?那就是追溯到订阅者父类的时候,搜索父类中的订阅方法,这时候存在同参方法是有些作用的;

现在我们先不按照源码逻辑走,先按照使用逻辑走;
当前订阅者中,肯定都是返回true,于是都添加到了List中,然后findUsingReflectionInSingleClass(findState)方法结束,走findState.moveToSuperclass()方法;

void moveToSuperclass() {
    if (skipSuperClasses) {
        clazz = null;
    } else {
        clazz = clazz.getSuperclass();
        String clazzName = clazz.getName();
        /** Skip system classes, this just degrades performance. */
        if (clazzName.startsWith("java.") || clazzName.startsWith("javax.") || clazzName.startsWith("android.")) {
            clazz = null;
        }
    }
}

如果跳过追寻超类则while循环就结束了,否则就clazz指向超类,同时加了一个限制条件,如果超类已经上升到了系统层那也到此结束;否则while循环跑起来;

又到了findUsingReflectionInSingleClass中,筛选后checkAdd;

这次进来,如果依旧不同参数则依旧返回true;如果参数和子类的参数一样则进入else,第一次进入else,Value还是Method类型,进入第一道签名检查;
在第一道签名检查中,如果参数类型相同但是方法名不同则MethodKey不同,直接通过检查;同时anyMethodByEventType标记了这个类型,将Value置为this;然后进入第二道签名检查,也是MethodKey不同,通过检查,添加到List;下一次再进入这里是什么时候呢?还是老样子,如果超类中出现两个以上的同参方法那就是你故意的,所以下一次就是超类的超类了;到了第三次,因为anyMethodByEventType对该参数类型做了this标记,所以这一次直接进入第二道检查,同样因为MethodKey不同,又通过检查;但是这样应该没人这么做,还不如直接在超类中定义一个方法,子类不停的super,发送事件的时候,直接在最超类中触发,然后调用该定义方法就行了;

这样是一种情况,现在来说一些不可能的情况,那就是订阅者中出现了同参不同名的方法,嗯,多个;这样最终还是通过签名检查,应为方法名不同,始终MethodKey不同;

再来一种情况,超类中存在和子类中同名同参的方法,这就有搞头了;第一道签名检查,因为是第一次来,所以MethodKey是第一次入库,所以通过第一道检查,第二道检查的时候

if (methodClassOld == null || methodClassOld.isAssignableFrom(methodClass)) 

因为不是第一次来了,所以第一个条件不成立,同样methodClassOld是methodClass的子类(为啥是他的子类,第一道检查,把子类扔进去了,第二道检查,把父类扔进去了,同时把子类返回来了,也就是methodClassOld),也不成立;所以直接进入了else中,重新把子类扔进去了,并返回false;这样父类中的订阅方法就被跳过去了,所以得出一个结论:

当订阅者已经订阅者的超类或者更超类中出现了同名同参的订阅方法,只有最底层的子类才会收到事件通知,超类以及以上该方法屏蔽;

这样通过while循环,找到所有合格订阅方法,并添加到了寻找状态的List中;

找到之后,最终返回getMethodsAndRelease(FindState findState);

private List<SubscriberMethod> getMethodsAndRelease(FindState findState) {
    List<SubscriberMethod> subscriberMethods = new ArrayList<>(findState.subscriberMethods);
    findState.recycle();
    synchronized (FIND_STATE_POOL) {
        for (int i = 0; i < POOL_SIZE; i++) {
            if (FIND_STATE_POOL[i] == null) {
                FIND_STATE_POOL[i] = findState;
                break;
            }
        }
    }
    return subscriberMethods;
}
void recycle() {
    subscriberMethods.clear();
    anyMethodByEventType.clear();
    subscriberClassByMethodKey.clear();
    methodKeyBuilder.setLength(0);
    subscriberClass = null;
    clazz = null;
    skipSuperClasses = false;
    subscriberInfo = null;
}

拿到寻找状态中的订阅方法List,然后释放寻找状态;
同时如果状态值没满就将寻找状态扔到状态池中;返回该订阅者所涉及的所有订阅方法;

现在回退几步;

List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
    ......
    if (ignoreGeneratedIndex) {
        subscriberMethods = findUsingReflection(subscriberClass);
    } else {
        subscriberMethods = findUsingInfo(subscriberClass);
    }
    ......
}

还记得这个吧,当初我们走的是设置忽略索引,现在来看看else中的findUsingInfo(subscriberClass);

private List<SubscriberMethod> findUsingInfo(Class<?> subscriberClass) {
    FindState findState = prepareFindState();
    findState.initForSubscriber(subscriberClass);
    while (findState.clazz != null) {
        findState.subscriberInfo = getSubscriberInfo(findState);
        if (findState.subscriberInfo != null) {
            SubscriberMethod[] array = findState.subscriberInfo.getSubscriberMethods();
            for (SubscriberMethod subscriberMethod : array) {
                if (findState.checkAdd(subscriberMethod.method, subscriberMethod.eventType)) {
                    findState.subscriberMethods.add(subscriberMethod);
                }
            }
        } else {
            findUsingReflectionInSingleClass(findState);
        }
        findState.moveToSuperclass();
    }
    return getMethodsAndRelease(findState);
}

仍然是寻找状态的初始化;

private SubscriberInfo getSubscriberInfo(FindState findState) {
    if (findState.subscriberInfo != null && findState.subscriberInfo.getSuperSubscriberInfo() != null) {
        SubscriberInfo superclassInfo = findState.subscriberInfo.getSuperSubscriberInfo();
        if (findState.clazz == superclassInfo.getSubscriberClass()) {
            return superclassInfo;
        }
    }
    if (subscriberInfoIndexes != null) {
        for (SubscriberInfoIndex index : subscriberInfoIndexes) {
            SubscriberInfo info = index.getSubscriberInfo(findState.clazz);
            if (info != null) {
                return info;
            }
        }
    }
    return null;
}

因为findState.subscriberInfo初始化的时候是null;subscriberInfoIndexes如果设置了索引就直接返回索引,否则就是null;如果有索引则直接在索引里面直接寻找合格的订阅方法;否则就和没索引一样,调用findUsingReflectionInSingleClass,去反射过滤出订阅方法,后续操作一样;

到这里我们的register就走过第二行代码了,尼玛。。。。。。

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

接着往下看,循环订阅:

private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
    Class<?> eventType = subscriberMethod.eventType;
    Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
    CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
    if (subscriptions == null) {
        subscriptions = new CopyOnWriteArrayList<>();
        subscriptionsByEventType.put(eventType, subscriptions);
    } else {
        if (subscriptions.contains(newSubscription)) {
            throw new EventBusException("Subscriber " + subscriber.getClass() + " already registered to event " + eventType);
        }
    }

    int size = subscriptions.size();
    for (int i = 0; i <= size; i++) {
        if (i == size || subscriberMethod.priority > subscriptions.get(i).subscriberMethod.priority) {
            subscriptions.add(i, newSubscription);
            break;
        }
    }

    List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);
    if (subscribedEvents == null) {
        subscribedEvents = new ArrayList<>();
        typesBySubscriber.put(subscriber, subscribedEvents);
    }
    subscribedEvents.add(eventType);

    if (subscriberMethod.sticky) {
        if (eventInheritance) {
            // Existing sticky events of all subclasses of eventType have to be considered.
            // Note: Iterating over all events may be inefficient with lots of sticky events,
            // thus data structure should be changed to allow a more efficient lookup
            // (e.g. an additional map storing sub classes of super classes: Class -> List<Class>).
            Set<Map.Entry<Class<?>, Object>> entries = stickyEvents.entrySet();
            for (Map.Entry<Class<?>, Object> entry : entries) {
                Class<?> candidateEventType = entry.getKey();
                if (eventType.isAssignableFrom(candidateEventType)) {
                    Object stickyEvent = entry.getValue();
                    checkPostStickyEventToSubscription(newSubscription, stickyEvent);
                }
            }
        } else {
            Object stickyEvent = stickyEvents.get(eventType);
            checkPostStickyEventToSubscription(newSubscription, stickyEvent);
        }
    }
}

我们传进来了订阅者和订阅方法;

获取订阅方法的参数类型;将订阅者和订阅方法组装成类订阅方法Subscription;根据参数类型找到所有属于该参数类型的类订阅方法的集合,然后塞进去;这里出现了一个subscriptionsByEventType,因为他是以参数类型作为Key而不是订阅者,又因为EventBus是单例,所以这个subscriptionsByEventType是针对全局的,针对APP中所有的已经register的订阅方法;

然后是针对这个集合中该参数类型所有的订阅方法根据优先级进行排序;

又出现了一个集合typesBySubscriber,这个是干嘛的呢?他以订阅者作为Key,这样就比较单一了,伴随着订阅者生生死死;他的Value是当前订阅者中所有参数类型的集合;

把当前参数类型对应着订阅者扔进去;

然后就到了黏性事件,黏性事件为什么会出现在这里?你在A里面发送了粘性事件,在B里面接收粘性事件,如果这时候B还没有register,那如何去接收事件呢,接收不到,难道这发送的事件就无效,所以有了粘性事件;该事件你发送了,我既然暂时接收不到,那我就先存着,反正是单例也跑不了,等我register的时候我再去存储库中看看黏性事件是否有需要我执行的;

回到代码,判断当前订阅事件是否是黏性事件;

eventInheritance可继承性;就是针对参数类型,如果A是B的父类,那发送B事件的时候,A、B参数的订阅事件都可以接收到事件;那看看他是怎么搞得:

Set<Map.Entry<Class<?>, Object>> entries = stickyEvents.entrySet();
for (Map.Entry<Class<?>, Object> entry : entries) {
    Class<?> candidateEventType = entry.getKey();
    if (eventType.isAssignableFrom(candidateEventType)) {
        Object stickyEvent = entry.getValue();
        checkPostStickyEventToSubscription(newSubscription, stickyEvent);
    }
}

stickyEvents也是全局的,Key是参数类型,Value是该参数类型的实例化对象;那这里面的值是哪来的呢,当发送黏性事件的时候就会存储进来;

isAssignableFrom这个还记得吧,就是用他来甄别是否是该类型的超类/接口;

获取该参数类型的对象;

private void checkPostStickyEventToSubscription(Subscription newSubscription, Object stickyEvent) {
    if (stickyEvent != null) {
        // If the subscriber is trying to abort the event, it will fail (event is not tracked in posting state)
    // --> Strange corner case, which we don't take care of here.
        postToSubscription(newSubscription, stickyEvent, isMainThread());
    }
}
private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {
    switch (subscription.subscriberMethod.threadMode) {
        case POSTING:
            invokeSubscriber(subscription, event);
            break;
        case MAIN:
            if (isMainThread) {
                invokeSubscriber(subscription, event);
            } else {
                mainThreadPoster.enqueue(subscription, event);
            }
            break;
        case MAIN_ORDERED:
            if (mainThreadPoster != null) {
                mainThreadPoster.enqueue(subscription, event);
            } else {
                // temporary: technically not correct as poster not decoupled from subscriber
                invokeSubscriber(subscription, event);
            }
            break;
        case BACKGROUND:
            if (isMainThread) {
                backgroundPoster.enqueue(subscription, event);
            } else {
                invokeSubscriber(subscription, event);
            }
            break;
        case ASYNC:
            asyncPoster.enqueue(subscription, event);
            break;
        default:
            throw new IllegalStateException("Unknown thread mode: " + subscription.subscriberMethod.threadMode);
    }
}

到了线程调度这一块,这一块开始就讲过了,应该还有点印象吧。

如果没指定线程,则默认POSTING:

invokeSubscriber(subscription, event);
void invokeSubscriber(Subscription subscription, Object event) {
    try {
        subscription.subscriberMethod.method.invoke(subscription.subscriber, event);
    } catch (InvocationTargetException e) {
        handleSubscriberException(subscription, event, e.getCause());
    } catch (IllegalAccessException e) {
        throw new IllegalStateException("Unexpected exception", e);
    }
}

将订阅方法和事件对象传入进来,然后反射调用注解方法,方法执行;over

如果制定了MAIN主线程:

if (isMainThread) {
    invokeSubscriber(subscription, event);
} else {
    mainThreadPoster.enqueue(subscription, event);
}

判断是否是主线程,如果是则直接在当前线程发射执行,否则调度到主线程中去执行;

private boolean isMainThread() {
    return mainThreadSupport != null ? mainThreadSupport.isMainThread() : true;
}

对mainThreadSupport进行判断,null直接默认主线程;

private final MainThreadSupport mainThreadSupport;

mainThreadSupport = builder.getMainThreadSupport();

去builder中看看;

    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;
        }
    }

不等于null直接返回,否则进入else if中看看

public static class AndroidLogger implements Logger {
    static final boolean ANDROID_LOG_AVAILABLE;

    static {
        boolean android = false;
        try {
            android = Class.forName("android.util.Log") != null;
        } catch (ClassNotFoundException e) {
            // OK
        }
        ANDROID_LOG_AVAILABLE = android;
    }

    public static boolean isAndroidLogAvailable() {
        return ANDROID_LOG_AVAILABLE;
    }
}

只要能找得到系统Log就可以继续

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

获取主线程的Looper;

public interface MainThreadSupport {

    boolean isMainThread();

    Poster createPoster(EventBus eventBus);

    class AndroidHandlerMainThreadSupport implements MainThreadSupport {

        private final Looper looper;

        public AndroidHandlerMainThreadSupport(Looper looper) {
            this.looper = looper;
        }

        @Override
        public boolean isMainThread() {
            return looper == Looper.myLooper();
        }

        @Override
        public Poster createPoster(EventBus eventBus) {
            return new HandlerPoster(eventBus, looper, 10);
        }
    }

}

将Looper传进来,绑定到HandlerPoster中;isMainThread()可以用来判断当前线程是否是主线程;这样就创建了基于主线程的MainThreadSupport;跑一圈其实就是拿当前线程和主线程作比较,看当前线程是否是主线程;

isMainThread()看完了再来看看是如何进行线程调度的;

mainThreadPoster.enqueue(subscription, event);
private final Poster mainThreadPoster;

mainThreadPoster = mainThreadSupport != null ? mainThreadSupport.createPoster(this) : null;

最终还是返回了绑定了主线程的HandlerPoster:

public class HandlerPoster extends Handler implements Poster {

    private final PendingPostQueue queue;
    private final int maxMillisInsideHandleMessage;
    private final EventBus eventBus;
    private boolean handlerActive;

    protected HandlerPoster(EventBus eventBus, Looper looper, int maxMillisInsideHandleMessage) {
        super(looper);
        this.eventBus = eventBus;
        this.maxMillisInsideHandleMessage = maxMillisInsideHandleMessage;
        queue = new PendingPostQueue();
    }

    public void enqueue(Subscription subscription, Object event) {
        PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
        synchronized (this) {
            queue.enqueue(pendingPost);
            if (!handlerActive) {
                handlerActive = true;
                if (!sendMessage(obtainMessage())) {
                    throw new EventBusException("Could not send handler message");
                }
            }
        }
    }

    @Override
    public void handleMessage(Message msg) {
        boolean rescheduled = false;
        try {
            long started = SystemClock.uptimeMillis();
            while (true) {
                PendingPost pendingPost = queue.poll();
                if (pendingPost == null) {
                    synchronized (this) {
                        // Check again, this time in synchronized
                        pendingPost = queue.poll();
                        if (pendingPost == null) {
                            handlerActive = false;
                            return;
                        }
                    }
                }
                eventBus.invokeSubscriber(pendingPost);
                long timeInMethod = SystemClock.uptimeMillis() - started;
                if (timeInMethod >= maxMillisInsideHandleMessage) {
                    if (!sendMessage(obtainMessage())) {
                        throw new EventBusException("Could not send handler message");
                    }
                    rescheduled = true;
                    return;
                }
            }
        } finally {
            handlerActive = rescheduled;
        }
    }
}

继承于Handler,实现了Poster接口;
创建的时候主要是赋值;
然后他调用了enqueue方法,这个方法都是干啥的?

public void enqueue(Subscription subscription, Object event) {
        PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
        synchronized (this) {
            queue.enqueue(pendingPost);
            if (!handlerActive) {
                handlerActive = true;
                if (!sendMessage(obtainMessage())) {
                    throw new EventBusException("Could not send handler message");
                }
            }
        }
    }

获取了一个PendingPost(还记得我们的约定吗?发送中事件),

final class PendingPost {
    private final static List<PendingPost> pendingPostPool = new ArrayList<PendingPost>();

    Object event;
    Subscription subscription;
    PendingPost next;

    private PendingPost(Object event, Subscription subscription) {
        this.event = event;
        this.subscription = subscription;
    }

    static PendingPost obtainPendingPost(Subscription subscription, Object event) {
        synchronized (pendingPostPool) {
            int size = pendingPostPool.size();
            if (size > 0) {
                PendingPost pendingPost = pendingPostPool.remove(size - 1);
                pendingPost.event = event;
                pendingPost.subscription = subscription;
                pendingPost.next = null;
                return pendingPost;
            }
        }
        return new PendingPost(event, subscription);
    }

    static void releasePendingPost(PendingPost pendingPost) {
        pendingPost.event = null;
        pendingPost.subscription = null;
        pendingPost.next = null;
        synchronized (pendingPostPool) {
            // Don't let the pool grow indefinitely
            if (pendingPostPool.size() < 10000) {
                pendingPostPool.add(pendingPost);
            }
        }
    }

}

他也是一个中间产物,主要是对发送过程中的状态值进行记录,他内部维持了一个大小为10000的状态池;

拿到这个发送中事件对象后,

private final PendingPostQueue queue;

queue.enqueue(pendingPost);
final class PendingPostQueue {
    private PendingPost head;
    private PendingPost tail;

    synchronized void enqueue(PendingPost pendingPost) {
        if (pendingPost == null) {
            throw new NullPointerException("null cannot be enqueued");
        }
        if (tail != null) {
            tail.next = pendingPost;
            tail = pendingPost;
        } else if (head == null) {
            head = tail = pendingPost;
        } else {
            throw new IllegalStateException("Head present, but no tail");
        }
        notifyAll();
    }

    synchronized PendingPost poll() {
        PendingPost pendingPost = head;
        if (head != null) {
            head = head.next;
            if (head == null) {
                tail = null;
            }
        }
        return pendingPost;
    }

    synchronized PendingPost poll(int maxMillisToWait) throws InterruptedException {
        if (head == null) {
            wait(maxMillisToWait);
        }
        return poll();
    }

}

看过数据结构就知道,他是一个链表的节点,有头尾指针;每次进来一个发送中事件就直接往链表后面扔;取用的时候是从头部取;每进来一个发送中事件就唤醒线程,抢夺时间片;

handlerActive就是一个标签,用作拦截,如果当前事件正在处理中,则拦截后续事件;

发送一个空消息;因为HandlerPoster是绑定了主线程的Looper,所以handleMessage在主线程中响应,线程调度成功;获取头部的发送中事件对象,然后调用eventBus.invokeSubscriber(pendingPost);

    void invokeSubscriber(PendingPost pendingPost) {
        Object event = pendingPost.event;
        Subscription subscription = pendingPost.subscription;
        PendingPost.releasePendingPost(pendingPost);
        if (subscription.active) {
            invokeSubscriber(subscription, event);
        }
    }

只是对发送中事件中的数据进行解析,然后反射调用订阅方法;

如果执行事件超过10毫秒则重新发送执行事件队列,防止排队空耗;

MAIN_ORDERED也是跟MAIN差不多;

BACKGROUND:

backgroundPoster.enqueue(subscription, event);
public void enqueue(Subscription subscription, Object event) {
        PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
        synchronized (this) {
            queue.enqueue(pendingPost);
            if (!executorRunning) {
                executorRunning = true;
                eventBus.getExecutorService().execute(this);
            }
        }
    }

也是添加到队列,设置标签,然后跑一个线程池;最后还是反射执行eventBus.invokeSubscriber(pendingPost);

ASYNC:

asyncPoster.enqueue(subscription, event);

这个也是跑一个线程池;最后还是反射执行eventBus.invokeSubscriber(pendingPost);

这样register就结束了;

开始post,可以和黏性事件并起来看:

EventBus 普通事件的post
EventBus 黏性事件的postSticky
EventBus 普通事件的unregister


参考
java中关键字volatile
Java反射中method.isBridge() 桥接方法
Java中的synthetic
Java中isAssignableFrom的用法
EventBus 普通事件的post
EventBus 黏性事件的postSticky
EventBus 普通事件的unregister


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值