EventBus使用和源码详解

目录

1. 架构图

2. 使用

3. 源码解析

3.1 @Subscribe注解

3.1.1 threadMode: 配置消息接收是在哪个线程

3.1.2 sticky : 粘性事件

3.1.3 priority :  接收事件的优先级

3.2 注解解析

3.2.1 注解类上的元注解

3.2.2  collectSubscribers收集订阅类和订阅的方法信息

3.2.3 生成MyEventBusIndex类

3.3 注册流程解析

3.3.1 注册流程

3.3.2 查找订阅方法findSubscriberMethods()

3.3.3 存储订阅类信息subscribe()

3.3.4 取消订阅

3.4 消息发送和接收解析

3.4.1 postSticky粘性消息

3.4.2 post普通消息

4. 总结


1. 架构图

从官网的架构图可以看出来,EventBus可以将发布者和订阅者解偶,这就是EventBus最大的方便之处。

2. 使用

请参考我的另外一篇文章:https://blog.csdn.net/fwt336/article/details/103133850

3. 源码解析

3.1 @Subscribe注解

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

    /**
     * If true, delivers the most recent sticky event (posted with
     * {@link EventBus#postSticky(Object)}) to this subscriber (if event available).
     */
    boolean sticky() default false;

    /** Subscriber priority to influence the order of event delivery.
     * Within the same delivery thread ({@link ThreadMode}), higher priority subscribers will receive events before
     * others with a lower priority. The default priority is 0. Note: the priority does *NOT* affect the order of
     * delivery among subscribers with different {@link ThreadMode}s! */
    int priority() default 0;
}

从Subscribe注解中的元注解可以看出来,我们的Subscribe是运行时注解,只能在运行时进行解析,也只能注册Method方法。

里面有三个参数可以进行配置:threadMode,sticky, priority。

3.1.1 threadMode: 配置消息接收是在哪个线程

有5种线程设置方式:

POSTING : 消息的接收与消息发送在同一个线程处理

MAIN : 消息在UI线程处理,但是如果发送线程是在UI线程,消息将会直接被调用处理,将阻塞调用线程。

MAIN_ORDERED : 消息在主线程处理,但是跟MAIN不一样的是,消息将会加入到队列中进行处理,不回堵塞调用线程。

BACKGROUND : 消息在后台线程处理,如果发送线程不是UI线程,则将会直接在发送线程处理消息。如果发送线程是UI线程,那么将使用一个后台线程,按照事件顺序处理。

ASYNC :消息将在单独的线程中调用,如果消息处理很耗时,可以采用这种方法,最终是EventBus使用线程池来处理消息。

3.1.2 sticky : 粘性事件

默认为false,如果设置为true,其作用与粘性广播的使用类似。也就是我们的粘性事件可以在事件注册前发送,当注册事件,并设置接收粘性事件后,将会接收到粘性事件。如果在注册之前发送了两个粘性事件,则只会接收到最后一个事件。

调用时,需用使用postSticky方法:

EventBus.getDefault().postSticky(new EventObject());

接收方法添加sticky = true即可,例如:

@Subscribe(threadMode = ThreadMode.Main, sticky = true)

stickyEventReceiver() {}

3.1.3 priority :  接收事件的优先级

在注册时将会用到这个参数,根据优先级加入到订阅者列表中。

3.2 注解解析

3.2.1 注解类上的元注解

先看看注解处理器上的注解修饰

@SupportedAnnotationTypes("org.greenrobot.eventbus.Subscribe")
@SupportedOptions(value = {"eventBusIndex", "verbose"})
public class EventBusAnnotationProcessor extends AbstractProcessor {}
SupportedAnnotationTypes : 指定处理器支持的处理类型
SupportedOptions : 用来表示所支持的附加选项

在运行apt命令行工具的时候,可以通过-A来传递额外的参数给注解处理器,如-Averbose=true。当通过 supportedOptions方法声明了所能识别的附加选项之后,注解处理器就可以在运行时刻通过AnnotationProcessorEnvironment的getOptions方法获取到选项的实际值。

public static final String OPTION_EVENT_BUS_INDEX = "eventBusIndex";
    public static final String OPTION_VERBOSE = "verbose";

@Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment env) {
            Messager messager = processingEnv.getMessager();
            String index = processingEnv.getOptions().get(OPTION_EVENT_BUS_INDEX);
            if (index == null) {
                messager.printMessage(Diagnostic.Kind.ERROR, "No option " + OPTION_EVENT_BUS_INDEX +
                        " passed to annotation processor");
                return false;
            }
            verbose = Boolean.parseBoolean(processingEnv.getOptions().get(OPTION_VERBOSE));
            int lastPeriod = index.lastIndexOf('.');
            String indexPackage = lastPeriod != -1 ? index.substring(0, lastPeriod) : null;

            round++;
            if (verbose) {
                messager.printMessage(Diagnostic.Kind.NOTE, "Processing round " + round + ", new annotations: " +
                        !annotations.isEmpty() + ", processingOver: " + env.processingOver());
            }
        return true;
    }
eventBusIndex选项值是注解器生成的一个类的路径,是必须要传递的一个值,它是在build.gradle中进行传递的:
android {

    defaultConfig {
        javaCompileOptions {
            annotationProcessorOptions {
                arguments = [eventBusIndex: 'org.greenrobot.eventbusperf.MyEventBusIndex']
            }
        }
    }
}

后面我们将会使用到这个类。

而verbose则是一个控制调试信息打印的变量,可传可不传。

3.2.2  collectSubscribers收集订阅类和订阅的方法信息

而我们的主要工作在下面三个方法上:

@Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment env) {
        Messager messager = processingEnv.getMessager();
        try {
            // ...
            collectSubscribers(annotations, env, messager); // 1.收集注解类和方法
            checkForSubscribersToSkip(messager, indexPackage); // 2.过滤事件

            if (!methodsByClass.isEmpty()) {
                createInfoIndexFile(index); // 3.生成MyEventBusIndex类
            } else {
                messager.printMessage(Diagnostic.Kind.WARNING, "No @Subscribe annotations found");
            }
            // ...
        } catch (RuntimeException e) {
        }
        return true;
    }

看下collectSubscribers源码:

private void collectSubscribers(Set<? extends TypeElement> annotations, RoundEnvironment env, Messager messager) {
        for (TypeElement annotation : annotations) {
            Set<? extends Element> elements = env.getElementsAnnotatedWith(annotation);
            for (Element element : elements) {
                if (element instanceof ExecutableElement) {
                    ExecutableElement method = (ExecutableElement) element;
                    if (checkHasNoErrors(method, messager)) {
                        TypeElement classElement = (TypeElement) method.getEnclosingElement();
                        methodsByClass.putElement(classElement, method);
                    }
                } else {
                    messager.printMessage(Diagnostic.Kind.ERROR, "@Subscribe is only valid for methods", element);
                }
            }
        }
    }

它会遍历每一个Subscriber标志信息,将标注的类和标注方法对应起来,存储到methodByClass里,方便后面使用。

同时,它还会检查方法是否被static修饰了,是不是被public修饰的,是否只有一个参数,也就是我们的事件参数只能是一个。

private boolean checkHasNoErrors(ExecutableElement element, Messager messager) {
        if (element.getModifiers().contains(Modifier.STATIC)) { // 检查是否有static修饰
            messager.printMessage(Diagnostic.Kind.ERROR, "Subscriber method must not be static", element);
            return false;
        }

        if (!element.getModifiers().contains(Modifier.PUBLIC)) { // 检查是不是public修饰的
            messager.printMessage(Diagnostic.Kind.ERROR, "Subscriber method must be public", element);
            return false;
        }

        List<? extends VariableElement> parameters = ((ExecutableElement) element).getParameters();
        if (parameters.size() != 1) { // 检查参数是否有且只有一个
            messager.printMessage(Diagnostic.Kind.ERROR, "Subscriber method must have exactly 1 parameter", element);
            return false;
        }
        return true;
    }

而我们收集到的数据methodsByClass将在checkForSubscribersToSkip方法和生成MyEventBusIndex时的writeIndexLines()方法中使用到。

checkForSubscribersToSkip流程:

private void checkForSubscribersToSkip(Messager messager, String myPackage) {
        for (TypeElement skipCandidate : methodsByClass.keySet()) {
            TypeElement subscriberClass = skipCandidate;
            while (subscriberClass != null) {
                if (!isVisible(myPackage, subscriberClass)) {  // 判断方法是否可见,public修饰或在同一个包内
                    boolean added = classesToSkip.add(skipCandidate);
                    break;
                }
                List<ExecutableElement> methods = methodsByClass.get(subscriberClass);
                if (methods != null) {
                    for (ExecutableElement method : methods) {
                        String skipReason = null;
                        VariableElement param = method.getParameters().get(0);
                        TypeMirror typeMirror = getParamTypeMirror(param, messager);
                        if (!(typeMirror instanceof DeclaredType) ||
                                !(((DeclaredType) typeMirror).asElement() instanceof TypeElement)) {
                            skipReason = "event type cannot be processed";
                        }
                        if (skipReason == null) {
                            TypeElement eventTypeElement = (TypeElement) ((DeclaredType) typeMirror).asElement();
                            if (!isVisible(myPackage, eventTypeElement)) {
                                skipReason = "event type is not public";
                            }
                        }
                        if (skipReason != null) {
                            boolean added = classesToSkip.add(skipCandidate);
                            break;
                        }
                    }
                }
// 遍历父类中的方法
                subscriberClass = getSuperclass(subscriberClass);
            }
        }
    }

a.首先会遍历所有标了Subscribe注解的类;

b.判断类是否可见,即是否有public修饰,或是否与MyEventBusIndex.java在同一个包内,或没有修饰符。不可见则放入classToSkip需要过滤的容器中;

private boolean isVisible(String myPackage, TypeElement typeElement) {
        Set<Modifier> modifiers = typeElement.getModifiers();
        boolean visible;
        if (modifiers.contains(Modifier.PUBLIC)) {
            visible = true;
        } else if (modifiers.contains(Modifier.PRIVATE) || modifiers.contains(Modifier.PROTECTED)) {
            visible = false;
        } else {
            String subscriberPackage = getPackageElement(typeElement).getQualifiedName().toString();
            if (myPackage == null) {
                visible = subscriberPackage.length() == 0;
            } else {
                visible = myPackage.equals(subscriberPackage);
            }
        }
        return visible;
    }

c.遍历Subscribe标注的类对应的所有注解方法;

d.判断Class是否是类或接口DeclaredType,不是则放入classToSkip需要过滤的容器中;

e.遍历父类,重复b,c,d方法

3.2.3 生成MyEventBusIndex类

配置生成EventBusIndex类使注解生成类生效

主要是看下writeIndexLines方法,其他生成的代码都是固定的:

private void writeIndexLines(BufferedWriter writer, String myPackage) throws IOException {
        for (TypeElement subscriberTypeElement : methodsByClass.keySet()) {
            if (classesToSkip.contains(subscriberTypeElement)) {
                continue;
            }

            String subscriberClass = getClassString(subscriberTypeElement, myPackage);
            if (isVisible(myPackage, subscriberTypeElement)) {
                writeLine(writer, 2,
                        "putIndex(new SimpleSubscriberInfo(" + subscriberClass + ".class,",
                        "true,", "new SubscriberMethodInfo[] {");
                List<ExecutableElement> methods = methodsByClass.get(subscriberTypeElement);
                writeCreateSubscriberMethods(writer, methods, "new SubscriberMethodInfo", myPackage);
                writer.write("        }));\n\n");
            } else {
                writer.write("        // Subscriber not visible to index: " + subscriberClass + "\n");
            }
        }
    }

也就是遍历我们收集到的带有@Subscribe注解的类,过滤出有效的类,再将我们的注册类名和注解参数封装起来,放入到SUBSCRIBER_INDEX这个map中,对外提供查找方法getSubscriberInfo()。

看下生成的这个类长什么样子:

package org.greenrobot.eventbusperf;

import org.greenrobot.eventbus.meta.SimpleSubscriberInfo;
import org.greenrobot.eventbus.meta.SubscriberMethodInfo;
import org.greenrobot.eventbus.meta.SubscriberInfo;
import org.greenrobot.eventbus.meta.SubscriberInfoIndex;

import org.greenrobot.eventbus.ThreadMode;

import java.util.HashMap;
import java.util.Map;

/** This class is generated by EventBus, do not edit. */
public class MyEventBusIndex implements SubscriberInfoIndex {
    private static final Map<Class<?>, SubscriberInfo> SUBSCRIBER_INDEX;

    static {
        SUBSCRIBER_INDEX = new HashMap<Class<?>, SubscriberInfo>();

        putIndex(new SimpleSubscriberInfo(TestRunnerActivity.class, true, new SubscriberMethodInfo[] {
            new SubscriberMethodInfo("onTestEvent", TestEvent.class, ThreadMode.MAIN),
        }));

        putIndex(new SimpleSubscriberInfo(TestActivity.class, true, new SubscriberMethodInfo[] {
            new SubscriberMethodInfo("onDemoEvent", TestEvent.class, ThreadMode.MAIN_ORDERED, 0, true),
        }));

    }

    private static void putIndex(SubscriberInfo info) {
        SUBSCRIBER_INDEX.put(info.getSubscriberClass(), info);
    }

    @Override
        public SubscriberInfo getSubscriberInfo(Class<?> subscriberClass) {
        SubscriberInfo info = SUBSCRIBER_INDEX.get(subscriberClass);
        if (info != null) {
            return info;
        } else {
            return null;
        }
    }
}

3.3 注册流程解析

3.3.1 注册流程

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

大致流程是:通过注册方法所在的类名,查找到所有注册类的订阅方法,然后在遍历每个订阅方法,将事件类型eventType跟订阅器Subscription(内部封装了订阅类所需的所有参数)存入到subscriptionsByEventType中,而subscriptionsByEventType在进行消息分发查找时将会用到Subscription数据。

3.3.2 查找订阅方法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;
        }
    }

从源码可以发现查找方法名有两种方式,一种时反射,另一种是通过获取注解处理器生成的类MyEventBusIndex获取,而默认ignoreGeneratedIndex是false。

反射查找所有方法则是通过获取注册类的所有方法,找到可见的且标注了@Subscribe注解的方法,然后封装成SubscriberMethod类返回一个SubscriberMethod的list。

通过注解类查找定制类型的所有方法

注解处理器生成类的注入:

/** Adds an index generated by EventBus' annotation preprocessor. */
    public EventBusBuilder addIndex(SubscriberInfoIndex index) {
        if (subscriberInfoIndexes == null) {
            subscriberInfoIndexes = new ArrayList<>();
        }
        subscriberInfoIndexes.add(index);
        return this;
    }

待用EventBusBuilder的addInex()方法后,这样,我们的注解处理器的作用才真正达到了。

但是,当没有配置注解器时,将强制使用反射方式进行处理。

那么问题来了,你在使用EventBus时配置了EventBusIndex类吗?

配置生成EventBusIndex类使注解生成类生效

3.3.3 存储订阅类信息subscribe()

我们将subscribe()方法分为三个部分来看。

a.存储订阅者信息

将订阅事件和订阅方法封装到Subscription中,然后以列表的形式存储在subscriptionsByEventType中,事件类型为key。而订阅事件发送的时候,也会从subscriptionsByEventType map中,将事件对应的subscriber订阅器信息取出来,然后进行消息事件的反射。

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

        // ...处理事件优先级

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

        //...处理粘性事件
    }

b. 处理消息事件优先级

private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
    // ... 
    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;
            }
        }
    // ...
}

每个方法插入列表的时候,将根据优先级插入,然后将列表保存在subscriptionsByEventType中。

c. 处理粘性消息

private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
        // ...
        if (subscriberMethod.sticky) {
            if (eventInheritance) {
                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);
            }
        }
    }
eventInheritance默认为true,所以会遍历整个stickyEvents,然后将stickyEvents中的消息事件分发出去:
private void checkPostStickyEventToSubscription(Subscription newSubscription, Object stickyEvent) {
        if (stickyEvent != null) {
            postToSubscription(newSubscription, stickyEvent, isMainThread()); // 分发给对应的poster处理
        }
    }

3.3.4 取消订阅

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

取消订阅就比较简单,只是将subscriptionsByEventType中对应的事件的注册类移除即可。

3.4 消息发送和接收解析

3.4.1 postSticky粘性消息

public void postSticky(Object event) {
        synchronized (stickyEvents) {
            stickyEvents.put(event.getClass(), event);
        }
        // Should be posted after it is putted, in case the subscriber wants to remove immediately
        post(event);
    }

通过源码我们可以发现,postSticky最终还是调用了post方法,只是会多一步将event加入stickyEvents中存储起来,当注册的时候会判断是否有对应可能的粘性事件。

3.4.2 post普通消息

public void post(Object event) {
        PostingThreadState postingState = currentPostingThreadState.get();
        List<Object> eventQueue = postingState.eventQueue;
        eventQueue.add(event);

        if (!postingState.isPosting) {
            postingState.isMainThread = isMainThread();
            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 = false;
            }
        }
    }

在post有会保存当前线程的一个状态,即PostingThreadState。但是查了下没有set方法,只有get,原来当没有有效值时,内部创建了一个默认的PostingThreadState。

private final ThreadLocal<PostingThreadState> currentPostingThreadState = new ThreadLocal<PostingThreadState>() {
        @Override
        protected PostingThreadState initialValue() {
            return new PostingThreadState();
        }
    };

当事件消息过来后,首先会通过ThreadLocal找到当前的线程PostingThreadState状态,获取到PostingThreadState中的队列,然后加入到队列中,如果此时线程正在分发消息,则退出,最后加入到消息将由正在分发消息的线程分发。

下面看下具体到消息分发:postSingleEvent(eventQueue.remove(0), postingState);

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

接着会获取到事件的类名,通过postSingleEventForEventType方法继续分发事件。

private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class<?> eventClass) {
        CopyOnWriteArrayList<Subscription> subscriptions;
        synchronized (this) {
            subscriptions = subscriptionsByEventType.get(eventClass);
        }
        if (subscriptions != null && !subscriptions.isEmpty()) {
            for (Subscription subscription : subscriptions) {
                postingState.event = event;
                postingState.subscription = subscription;
                boolean aborted = false;
                try {
                    postToSubscription(subscription, event, postingState.isMainThread);
                    aborted = postingState.canceled;
                } finally {
                    postingState.event = null;
                    postingState.subscription = null;
                    postingState.canceled = false;
                }
                if (aborted) {
                    break;
                }
            }
            return true;
        }
        return false;
    }

最终通过事件类名从subscriptionsByEventType集合中找到对应的所有订阅类,而我们在注册的时候,将事件类名和订阅类存入到类subscriptionsByEventType中。

找到所有的订阅类subscriptions后,遍历所有订阅类,然后通过postToSubscription方法进行具体的消息分发处理。

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

最终会通过初始化时的分发器,根据threadMode类型进行消息的处理。如果是posting线程则直接调用invokeSubscriber处理,如果是后台线程或者异步线程,则都是调用EventBus的线程池进行处理消息队列中的消息,而UI线程则是通过handler进行处理。

看下mainPoster的代码就知道了,确实是通过new HandlerPoster处理的,而HandlerPoster继承了Handler,并实现了Poster接口:

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

重点来了,最后所有消息处理都是通过反射实现的:

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

终于看到了久违的invoke方法!

4. 总结

EventBus可以通过注解和反射两种方式来获取到订阅者的相关信息,然后通过UI线程或内部的线程池处理发送的消息事件,最终是通过反射实现订阅者方法的调用,有订阅者处理消息。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章