EventBus 3.1.1 源码解析(一)


EventBus 是一个事件发布/订阅框架,通过解耦发布者和订阅者简化 Android 事件传递,这里的事件可以理解为消息,本文中统一称为事件。事件传递既可用于 Android 四大组件间通讯,也可以用户异步线程和主线程间通讯等等。

EventBus简化了各组件间的通信,有效的分离事件发送方和接收方(也就是解耦的意思),避免复杂和容易出错的依赖性和生命周期问题。

类似于broadcastReceiver,EventBus比广播效率高。广播机制采用的观察者模式,即只要app注册了对广播的监听,广播发出的时候,就可以监听到。动态注册的广播必须动态取消。同样的,eventBus也需要注册和取消注册。

EventBus是按事件eventType来标记的,所有注册了,且标记了eventType的都会收到消息。

EventBus github地址:

依赖引入:

compile 'org.greenrobot:eventbus:3.1.1'

在Activity 的onCreate() / onDestroy() 中分别register/unregister

EventBus.getDefault().register(this);

EventBus.getDefault().unregister(this);

//EventBus在合适的时机发出一个消息。可以任意定义消息
EventBus.getDefault().post(new AuthFailedMsg());

//在哪里进行接收处理呢?在刚刚注册、反注册的生命周期内可接收到消息并进行处理。
//可以指定threadMode、priority、sticky
@Subscribe(threadMode = ThreadMode.BACKGROUND, priority = 10, sticky = false)
public void onAuthFailed(AuthFailedMsg msg) {
    //身份过期, 清除用户缓存,跳转到登陆页面
    Intent i = new Intent(this, LoginActivity.class);
    startActivity(i);
}

总而言之:

  • 在Activity的注册和反注册生命周期内,eventBus发出消息
  • @subscriber注解标记的method如果入参和发出的消息类型匹配,即可进行消息的处理。

EventBus源码解析:

鉴于EventBus源码较少,所以全部铺开来看了。

@Subscriber可以标记threadMode、priority、sticky (priority数字越大,优先级最高)

@Subscribe(threadMode = ThreadMode.BACKGROUND, priority = 10, sticky = false)

Sticky 事件不同之处在于,当事件发布后,再有订阅者开始订阅该类型事件,依然能收到该类型事件最近一个 Sticky 事件。

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface Subscribe {
    ThreadMode threadMode() default ThreadMode.POSTING;

    boolean sticky() default false;

    int priority() default 0;
}

1、获得EventBus实例

EventBus.getDefault(),单例模式(可保证同步),整个应用内只有一个实例。

//EventBus.java
private static final EventBusBuilder DEFAULT_BUILDER = new EventBusBuilder();

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

public EventBus() {
   this(DEFAULT_BUILDER);
}

EventBus(EventBusBuilder builder) {
        logger = builder.getLogger();
        subscriptionsByEventType = new HashMap<>(); //eventType对应的subscriptions
        typesBySubscriber = new HashMap<>(); //subscriber对应的eventType
        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;
    }

EventBusBuilder.java

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

2、register() 注册

public void register(Object subscriber) { //注册的是个对象
        Class<?> subscriberClass = subscriber.getClass(); //得到注册对象的class,subscriberClass
        List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
        synchronized (this) {
            for (SubscriberMethod subscriberMethod : subscriberMethods) {
                subscribe(subscriber, subscriberMethod);
            }
        }
    }

SubscriberMethodFinder # findSubscriberMethods()

其实是加了一层缓存,CACHE_METHOD

private final boolean ignoreGeneratedIndex;
private static final Map<Class<?>, List<SubscriberMethod>> METHOD_CACHE = new ConcurrentHashMap<>();

 List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
 		//如果缓存里有就从缓存里取
        List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass); 
        if (subscriberMethods != null) {
            return subscriberMethods;
        }

        if (ignoreGeneratedIndex) {
            subscriberMethods = findUsingReflection(subscriberClass); //通过反射的方式找subscriberMethods
        } else {
            subscriberMethods = findUsingInfo(subscriberClass); //通过APT
        }
        //如果subscriberMethods.isEmpty会报错
        //也就是说注册的对象必须有通过@subscribe注解的有效方法
        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;
        }
    }

2.1、SubscriberMethodFinder#findUsingReflection()

通过反射的方式得到List< SubscriberMethod>

  • 准备一个FindState对象
  • 初始化FindState对象
  • 循环遍历,默认是可以向superClass一直找,直到findState.clazz为null
  • 检查是否有通过@subscriber标记的有效方法
    private List<SubscriberMethod> findUsingReflection(Class<?> subscriberClass) {
        FindState findState = prepareFindState(); //准备一个FindState对象
        findState.initForSubscriber(subscriberClass); //初始化FindState对象
        while (findState.clazz != null) { //clazz为注册对象的类,也就是subscriberClass
            findUsingReflectionInSingleClass(findState); //
            findState.moveToSuperclass(); //默认是找父类,看是否有通过@subscriber标记的方法
        }
        return getMethodsAndRelease(findState);
    }

SubscriberMethodFinder # prepareFindState()

如果FIND_STATE_POOL中有不为null的对象,取出来进行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();
    }

SubscriberMethodFinder # findUsingReflectionInSingleClass()

  • public Method[] getMethods():返回某个类、及其继承类(父类)、和所实现接口的所有公用方法。
  • public Method[] getDeclaredMethods():返回某个类、和所实现接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承(父类)的任何方法。

定义Method数组,通过反射的方式拿到注册类subscribeClass的所有methods,且必须是public方法,non-static,non-abstract,有且只有一个入参,入参类型即为eventType,通过@subscribe注解标注。

如果此类中没有一个method满足这些条件,findState.moveToSuperClass()

private void findUsingReflectionInSingleClass(FindState findState) {
        Method[] methods; //定义Method数组
        try {
            // This is faster than getMethods, especially when subscribers are fat classes like Activities
            methods = findState.clazz.getDeclaredMethods();
        } catch (Throwable th) {
            // Workaround for java.lang.NoClassDefFoundError, see https://github.com/greenrobot/EventBus/issues/149
            methods = findState.clazz.getMethods();
            findState.skipSuperClasses = true; //因为getMethods()里包含了继承的超类,所以接下来要跳过继承类
        }
        for (Method method : methods) { //遍历所有Method
            int modifiers = method.getModifiers(); 
            if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) {
                Class<?>[] parameterTypes = method.getParameterTypes();
                if (parameterTypes.length == 1) {
                    Subscribe subscribeAnnotation = method.getAnnotation(Subscribe.class);
                    if (subscribeAnnotation != null) {
                        Class<?> eventType = parameterTypes[0];
                        if (findState.checkAdd(method, eventType)) {
                            ThreadMode threadMode = subscribeAnnotation.threadMode();
                            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)) {
                String methodName = method.getDeclaringClass().getName() + "." + method.getName();
                throw new EventBusException(methodName +
                        " is a illegal @Subscribe method: must be public, non-static, and non-abstract");
            }
        }
    }

如果此类中存在method满足这些条件,就进入到下面的分析

  • findState.checkAdd(method, eventType)给anyMethodByEventType或者subscriberClassByMethodKey赋值
Class<?> eventType = parameterTypes[0];  //method的入参类型
if (findState.checkAdd(method, eventType)) {
ThreadMode threadMode = subscribeAnnotation.threadMode(); //获取线程模式
findState.subscriberMethods.add(new SubscriberMethod(method, eventType, threadMode,
   subscribeAnnotation.priority(), subscribeAnnotation.sticky()));
}
 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;
    }

SubscriberMethodFinder # getMethodAndRelease()

  • 也有可能findState.subscriberMethod里并没有对象,所以,但是会报错"Subscriber " + subscriberClass + " and its super classes have no public methods with the @Subscribe annotation"

  • 这里有个小问题哈,为啥把使用完成的findState赋给缓冲池,下次从缓冲池里取出这个不为null的FindState进行复用呢?为什么不从缓冲池里取出一个null对象进行使用,然后使用完成后再赋null。

 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; //把使用完成的findState赋给缓冲池
                    break;
                }
            }
        }
        return subscriberMethods;
    }

FindState是SubscriberMethodFinder的静态内部类

static class FindState {
        final List<SubscriberMethod> subscriberMethods = new ArrayList<>();
        final Map<Class, Object> anyMethodByEventType = new HashMap<>();
        final Map<String, Class> subscriberClassByMethodKey = new HashMap<>();
        final StringBuilder methodKeyBuilder = new StringBuilder(128);

        Class<?> subscriberClass;
        Class<?> clazz;
        boolean skipSuperClasses;
        SubscriberInfo subscriberInfo;

        void initForSubscriber(Class<?> subscriberClass) {
            this.subscriberClass = clazz = subscriberClass; //subscriberClass和clazz都为注册对象的类
            skipSuperClasses = false; //默认为false
            subscriberInfo = null; //默认为null
        }

        void recycle() { //初始化,清除引用
            subscriberMethods.clear();  //subscriberMethods清空
            anyMethodByEventType.clear();  //anyMethodByEventType清空
            subscriberClassByMethodKey.clear(); //subscriberClassByMethodKey清空
            methodKeyBuilder.setLength(0);
            subscriberClass = null;
            clazz = null;
            skipSuperClasses = false;
            subscriberInfo = null;
        }

//两级校对,一般来说,一个subscriberClass对同一个eventType只会做一次监听
//假如一个subscriberClass对同一个eventType做了多次监听,即一个类里通过@subscriber标记且入参类型相同的的方法有多个
        boolean checkAdd(Method method, Class<?> eventType) { //传入method和method的入参类型
            Object existing = anyMethodByEventType.put(eventType, method);
            if (existing == null) {
                return true; //只做了一次监听,简简单单
            } else {
                if (existing instanceof Method) { //existing是通过@subscriber标记的旧方法
                    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); //method是通过@subscriber标记的新方法
            }
        }

//给subscriberClassByMethodKey赋值("方法名>方法入参类型", 方法所属类的类对象methodClass)
//这意味着一个类如果使用了多个方法对同一个 Event 对象进行注册,那么当该 Event 对象被发送出来的时候,所有的方法都将会得到回调。
        private boolean checkAddWithMethodSignature(Method method, Class<?> eventType) {
            methodKeyBuilder.setLength(0); //methodKeyBuilder是一个128位的StringBuilder
            methodKeyBuilder.append(method.getName()); //方法名肯定唯一
            methodKeyBuilder.append('>').append(eventType.getName()); 

            String methodKey = methodKeyBuilder.toString(); //methodKey为"方法名>方法入参类型"
            Class<?> methodClass = method.getDeclaringClass(); //得到方法所属类的类对象methodClass
            Class<?> methodClassOld = subscriberClassByMethodKey.put(methodKey, methodClass); //
            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
                //当子类「显示」实现父类的订阅方法的时候,如果此时发射指定 Event的话,
                //父类的订阅方法将不会执行,而仅会执行子类的订阅方法。
                subscriberClassByMethodKey.put(methodKey, methodClassOld);
                return false;
            }
        }

        void moveToSuperclass() {
            if (skipSuperClasses) { //初始化的时候默认为false
                clazz = null; //清空clazz 
            } else {
                clazz = clazz.getSuperclass(); //找subscribeClass的父类,
                String clazzName = clazz.getName();
                /** Skip system classes, this just degrades performance. */
                if (clazzName.startsWith("java.") || clazzName.startsWith("javax.") || clazzName.startsWith("android.")) {
                    clazz = null;
                }
            }
        }
    }

注册过程最终又回到:遍历subscriberMethods,

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 final Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType;

 private final Map<Object, List<Class<?>>> typesBySubscriber; //用于反注册,发送消息没用到

    // Must be called in synchronized block
    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) { //eventType对应的Subscription
            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); //subscriber对应的eventType
        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(Object subscriber, SubscriberMethod subscriberMethod) {
        this.subscriber = subscriber;
        this.subscriberMethod = subscriberMethod;
        active = true;
    }

注册到这里算是结束了。

  • 首先根据subscriber找到该类通过@Subscribe标记的所有SubscriberMethod

  • 遍历所有的subscriberMethod

  • subscriptionsByEventType存入eventType和CopyOnWriteArrayList的对应关系,新的这个subscriberMethod封装成Subscription对象,按优先级存入CopyOnWriteArrayList中。消息类型 -> 订阅者/订阅方法

  • typesBySubscriber存入subscriber和List的对应关系,这个eventType添加到List。订阅者 -> 消息类型

3、unregister() 取消注册

  • typesBySubscriber 根据反注册对象subscriber找到List

  • 遍历eventType,subscriptionsByEventType 根据eventType找到List

  • 遍历subscription,如果subscription的subscriber和需要反注册的对象一致,则remove掉这个subscription。反注册对象对应的每个subscribeMethod去掉了。

  • 最终remove掉这个typesBySubscriber中的subscriber。反注册对象也清掉了。

    public synchronized void unregister(Object subscriber) {
        List<Class<?>> subscribedTypes = typesBySubscriber.get(subscriber);
        if (subscribedTypes != null) {
            for (Class<?> eventType : subscribedTypes) {
                unsubscribeByEventType(subscriber, eventType);
            }
            typesBySubscriber.remove(subscriber);
        } else { //如果根据订阅者没有找到订阅的消息类型,则没有注册过
            logger.log(Level.WARNING, "Subscriber to unregister was not registered before: " + subscriber.getClass());
        }
    } 
    
    private void unsubscribeByEventType(Object subscriber, Class<?> eventType) {
        List<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
        if (subscriptions != null) {
            int size = subscriptions.size();
            for (int i = 0; i < size; i++) {
                Subscription subscription = subscriptions.get(i);
                if (subscription.subscriber == subscriber) {
                    subscription.active = false; 
                    subscriptions.remove(i);
                    i--;
                    size--;
                }
            }
        }
    }

4、post发送消息

PostingThreadState是EventBus中的静态内部类。

EventBus # post()

private final ThreadLocal<PostingThreadState> currentPostingThreadState = new ThreadLocal<PostingThreadState>() {
        @Override
        protected PostingThreadState initialValue() {
            return new PostingThreadState();
        }
    };
    
     final static class PostingThreadState {
        final List<Object> eventQueue = new ArrayList<>(); //消息或者说事件队列
        boolean isPosting; //是否在分发处理中
        boolean isMainThread; //是否是主线程
        Subscription subscription; //封装了subscriber和subscriberMethod
        // (subscriberMethod又封装了method/eventType/threadMode/priority/sticky)
        Object event; //事件
        boolean canceled; //是否被取消
    }
    
public void post(Object event) {
        PostingThreadState postingState = currentPostingThreadState.get(); //
        List<Object> eventQueue = postingState.eventQueue;
        eventQueue.add(event); //将要发送的event加入到PostingThreadState中的eventQueue中。

        if (!postingState.isPosting) { //确保不会被调用多次
            postingState.isMainThread = isMainThread(); //初始化postingState的isMainThread和isPosting
            postingState.isPosting = true;
            if (postingState.canceled) {
                throw new EventBusException("Internal error. Abort state was not reset");
            }
            try {
                while (!eventQueue.isEmpty()) {
                    postSingleEvent(eventQueue.remove(0), postingState);
                }
            } finally {
                postingState.isPosting = false; //还原postingState的的isMainThread和isPosting
                postingState.isMainThread = false;
            }
        }
    }

EventBus # postSingleEvent()

eventInheritance:事件eventType之间是否存在继承关系,如果没有,可以设置为false

private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {
        Class<?> eventClass = event.getClass();
        boolean subscriptionFound = false;
        if (eventInheritance) { 
            List<Class<?>> eventTypes = lookupAllEventTypes(eventClass);
            int countTypes = eventTypes.size();
            for (int h = 0; h < countTypes; h++) {
                Class<?> clazz = eventTypes.get(h);
                subscriptionFound |= postSingleEventForEventType(event, postingState, clazz);
            }
        } else {
            subscriptionFound = postSingleEventForEventType(event, postingState, eventClass);
        }
        if (!subscriptionFound) {
            if (logNoSubscriberMessages) {
                logger.log(Level.FINE, "No subscribers registered for event " + eventClass);
            }
            if (sendNoSubscriberEvent && eventClass != NoSubscriberEvent.class &&
                    eventClass != SubscriberExceptionEvent.class) {
                post(new NoSubscriberEvent(this, event));
            }
        }
    }

EventBus # postSingleEventForEventType()

private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class<?> eventClass) {
        CopyOnWriteArrayList<Subscription> subscriptions;
        synchronized (this) {
            subscriptions = subscriptionsByEventType.get(eventClass); //根据eventType得到subscriptions
        }
        if (subscriptions != null && !subscriptions.isEmpty()) { 
            for (Subscription subscription : subscriptions) { 遍历subscriptions,
                postingState.event = event; //给postingState的event和subscription赋值
                postingState.subscription = subscription;
                boolean aborted = false;
                try {
                    postToSubscription(subscription, event, postingState.isMainThread);
                    aborted = postingState.canceled;
                } finally {
                    postingState.event = null; // 还原postingState的event和subscription状态
                    postingState.subscription = null;
                    postingState.canceled = false;
                }
                if (aborted) {
                    break;
                }
            }
            return true;
        }
        return false;
    }

EventBus # postToSubscription()

EventBus可以实现跨线程调度:需要注意的是,在主线程中不应该执行过多耗时操作

  • POSTING: 接收事件方法和发送事件方法在同一个线程中执行(由于发射事件方法线程可能是主线程,这意味着接收方法不能执行耗时操作,否则会阻塞主线程)

  • MAIN: 接收事件方法在主线程中执行,不管发送事件是在主线程还是子线程。如果发送事件是在主线程,则接收事件会立即执行,否则会被扔进 MessageQueue 中进行等待执行。

  • MAIN_ORDERED: 在 Android 中则接收事件方法会被扔进 MessageQueue 中等待执行(这意味着发射事件方法是不会被阻塞的)。

  • BACKGROUND: 如果是在主线程中发送事件,则接收事件方法应执行在子线程执行,但该子线程是 EventBus 维护的单一子线程,所以为了避免影响到其他接收事件方法的执行,该方法不应太耗时避免该子线程阻塞。
    如果发送事件是在子线程中执行的,则接收事件与发送事件在同一个子线程中执行。

  • ASYNC: 接收事件和发送事件不在同一个线程中,且接收事件不会在子线程。常用于耗时操作,例如网络访问。当然,尽量避免在同一个时间大量触发此类型方法,尽管 EventBus 为此专门创建了线程池来管理回收利用这些线程。

public enum ThreadMode {
    POSTING, 
    MAIN,
    MAIN_ORDERED,
    BACKGROUND,
    ASYNC
}
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进行线程调度
                    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进行线程调度
                    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);
        }
    }

在FirstActivity的主线程中发送了一个消息,并对同一中EventType消息事件做了5次监听,指定不同线程

  • Posting是在同一个线程中
  • BACKGROUND维护单一子线程
  • ASYNC每次都会创建不同线程
  • thread.toString()打印出来的是线程名、优先级和线程组

在FirstActivity的子线程中发送了一个消息,并对同一种EventType消息事件做了5次监听,指定不同线程

  • 如果发送事件已经是在子线程中,则直接执行

利用反射的方式直接执行

 void invokeSubscriber(PendingPost pendingPost) {
        Object event = pendingPost.event;
        Subscription subscription = pendingPost.subscription;
        PendingPost.releasePendingPost(pendingPost);
        if (subscription.active) {
            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);
        }
    }

5、Poster

最后来看看EventBus是怎么来实现线程调度的

mainThreadPoster、backgroundPoster、asyncPoster是在EventBus初始化的时候实例化的。

mainThreadPoster、backgroundPoster、asyncPoster都实现了Poster接口。

mainThreadPoster:

backgroundPoster:

asyncPoster:

interface Poster {
    void enqueue(Subscription subscription, Object event);
}
mainThreadPoster = mainThreadSupport != null ? mainThreadSupport.createPoster(this) : null;
backgroundPoster = new BackgroundPoster(this);
asyncPoster = new AsyncPoster(this);

5.1 BackgroundPoster

  • eventBus.getExecutorService() 是在EventBus实例化时初始化的,Executors.newCachedThreadPool()

  • 前面我们说了BACKGROUND维护单一子线程,但是Executors.newCachedThreadPool()里维护的线程可以有Integer.MAX_VALUE个。

  • executorRunning是实现单一线程池的关键,volatile修饰,用作标志位,保证同一时刻只有一个线程处于运行状态

volatile保证可见性:
一旦一个共享变量(类的成员变量、类的静态成员变量)被volatile修饰之后,那么就具备了两层语义:

* 保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了这个变量的值,这新值对其他线程来说是立即可见的。
* 禁止进行指令重排序。(有序性)
* 不能保证原子性
final class BackgroundPoster implements Runnable, Poster {

    private final PendingPostQueue queue;
    private final EventBus eventBus;

    private volatile boolean executorRunning;

    BackgroundPoster(EventBus eventBus) {
        this.eventBus = eventBus;
        queue = new PendingPostQueue(); //EventBus实例化时,初始化
    }

    public void enqueue(Subscription subscription, Object event) { //实现的Poster接口
        PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event); 
        //从缓冲池取出一个pendingPost, 并给pendingPost的event和subscription赋值
        synchronized (this) {
            queue.enqueue(pendingPost); //将初始化完成的pendingPost入队
            if (!executorRunning) { 
                executorRunning = true; //标记开始执行
                eventBus.getExecutorService().execute(this); //线程池中执行当前runnable对象
            }
        }
    }

    @Override
    public void run() {
        try {
            try {
                while (true) {
                    PendingPost pendingPost = queue.poll(1000); 
                    //延时1s,从queue中取出一个pendingPost,不一定是刚入队的pendingPost
                    if (pendingPost == null) {
                        synchronized (this) {
                            // Check again, this time in synchronized
                            pendingPost = queue.poll();
                            if (pendingPost == null) {
                                executorRunning = false;
                                return;
                            }
                        }
                    }
                    eventBus.invokeSubscriber(pendingPost); //
                }
            } catch (InterruptedException e) {
                eventBus.getLogger().log(Level.WARNING, Thread.currentThread().getName() + " was interruppted", e);
            }
        } finally {
            executorRunning = false;
        }
    }

}

PendingPostQueue

PendingPostQueue是一个采用单链表实现的队列,先进先出,或者说后进后出。

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

PendingPost

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

    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) { // obtain
        synchronized (pendingPostPool) {
            int size = pendingPostPool.size();
            if (size > 0) {
                PendingPost pendingPost = pendingPostPool.remove(size - 1); //取出最后一个PendingPost
                pendingPost.event = event; //对pendingPost进行赋值
                pendingPost.subscription = subscription;
                pendingPost.next = null;
                return pendingPost;
            }
        }
        return new PendingPost(event, subscription);
    }

    static void releasePendingPost(PendingPost pendingPost) { //release
        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);
            }
        }
    }

}

5.2 AsyncPoster

相比BackgroundPoster简单很多,最主要的区别就是少了一个volatile标记executorRunning

AsynPoster始终执行在一个新的子线程中,既区别于发送消息的线程,也区别于主线程

class AsyncPoster implements Runnable, Poster {

    private final PendingPostQueue queue;
    private final EventBus eventBus;

    AsyncPoster(EventBus eventBus) {
        this.eventBus = eventBus;
        queue = new PendingPostQueue();
    }

    public void enqueue(Subscription subscription, Object event) {
        PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
        queue.enqueue(pendingPost);
        eventBus.getExecutorService().execute(this);
    }

    @Override
    public void run() {
        PendingPost pendingPost = queue.poll();
        if(pendingPost == null) {
            throw new IllegalStateException("No pending post available");
        }
        eventBus.invokeSubscriber(pendingPost);
    }

}

5.3 mainThreadPoster

mainThreadPoster其实是HandlerPoster实现的,得到主线程的looper对象

然后通过这个主线程的handler进行主线程上消息的执行

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); // handler是主线程的handler
        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) { //主线程的handler当然在主线程处理消息啦
        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;
        }
    }
}
取消事件的传递:

example:
TestAActivity和TestBActivity在onCreate和onDestroy内分别注册和反注册了EventBus。TestAActivity点击按钮启动TestBActivity,TestBActivity点击按钮发送一个Event事件,则TestAActivity和TestBActivity都能响应这个event事件(TestAActivity还没有执行到onDestroy())。
TestAActivity和TestBActivity都继承自BaseAcitivity,BaseActivity在onCreate和onDestroy内分别注册和反注册了EventBus。表现现象和上面一致()。

事件取消后就不会再传递

// Called in the same thread (default)
@Subscribe
public void onEvent(MessageEvent event){
// Process the event
…

EventBus.getDefault().cancelEventDelivery(event) ;
}

6、总结

  • 使用上:就是注册register和反注册unRegister的生命周期内可以监听到post出的event事件。

  • 实现上:

  • 注册:把当前注册类的所有通过@subscriber标记的方法找出来;形成eventType和list的对应关系,并把不同或者相同eventType的subscription放入list中;subscription包含了subscriber和和subscriberMethod,subscriberMethod包含了method、eventType、threadMode、priority、sticky;形成注册类subscriber和eventType的对应关系。

  • 反注册:把当前反注册类subscriber监听的所有eventType找出来,再根据eventType找到list,匹配subscription,如果subscriber和当前反注册的类相同,则remove掉。最终也移除掉反注册类和eventType的关系。

  • 发送消息:根据eventType找到list,遍历每个subscription,进行事件消息分发调度。


参考:

聊一聊 EventBus 源码和设计之禅

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值