EventBus源码解析

作者: 砺雪凝霜 | 来源:发表于2018-01-22 15:14 被阅读96次

(1)eventbus的使用

为了方便分析EventBus的源码,这里我们先整个demo出来,源码如下:

public class MainActivity extends AppCompatActivity {

    private TextView tvMessage;
    private View btnSecond;
    private Button btnRegister;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        EventBus.getDefault().register(this);

        tvMessage = findViewById(R.id.tv_message);
        btnSecond = findViewById(R.id.btn_second);
        btnRegister = findViewById(R.id.tv_register);

        btnRegister.setOnClickListener(new View.OnClickListener(){

            @Override
            public void onClick(View v) {

            }
        });
        btnSecond.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MainActivity.this,SecondActivity.class);
                startActivity(intent);
            }
        });
       loadData("http://www.baidu.com");
    }

    public void loadData(final String url){
        new Thread(){
            @Override
            public void run() {
                super.run();
                String json = "message from MainActivity";
                MessageEvent messageEvent = new MessageEvent("recode",json,"msg");
                //在子线程当中发布类给主线程
                // EventBus.getDefault().post(json);
                EventBus.getDefault().post(messageEvent);
            }
        }.start();
    }


  //  @Subscribe(threadMode = ThreadMode.MAIN,sticky = true)//MAIN代表主线程
   @Subscribe(threadMode = ThreadMode.MAIN,sticky = false)
    public void receiveMessage(MessageEvent messageEvent){//该方法名可更改,不影响任何东西。
        //在主线程中获取子线程发送来的消息设置到TextView中
        tvMessage.setText(messageEvent.getResult());
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        EventBus.getDefault().unregister(this);
    }
}

(2)EventBus的register过程

  • EventBus的初始化
 public static EventBus getDefault() {
        if (defaultInstance == null) {
            synchronized (EventBus.class) {
                if (defaultInstance == null) {
                    defaultInstance = new EventBus();
                }
            }
        }
        return defaultInstance;
    }

可以看出:EventBus调用getDefault方法进行初始化,并且使用了双重否定的单例模式。

  • EventBus调用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);
            }
        }
    }
  • Subscriber:订阅者对象,对应demo中的MainActivity
  • SubscriberMethod:是我们在Activity中定义的订阅方法的一个描述类,里面保存了订阅方法的信息,其实就是我们在Activity中定义的用@Subscriber注解修饰的receiveMessage(MessageEvent)方法。这里我截取了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;
    }

method:方法名
ThreadMode:注解名称
eventType:消息类型的字节码对象,对应demo中MessageEvent的class对象
priority:注解中priority属性,表示方法执行的优先级

  • EventBus是如何找到subscriberMethod的集合的呢?

subscriberMethodFinder调用findSubscriberMethods(subscriberClass)方法找到了Subscriber对象(MainActivity)中所有订阅方法信息的集合。

那么findSubscriberMethods是如何找到SubscriberMethod的呢?

我们接着往下看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:EventBus对Subscriber订阅者的订阅方法做的一个缓存,它是一个Map对象,key是Subscriber对象,因为Subscriber对象可能有多个订阅方法,所以value是Subscriber对应的订阅方法的集合。

可以看出EventBus先会从缓存中拿Subscriber对应的SubscriberMethod的集合,如果缓存不为空,直接从缓存中获取。

  • ignoreGeneratedIndex:这个参数默认是为false,表示使用@Subscribe注解,EventBus3.0版本后默认使用该注解来表示订阅方法。而在EventBus3.0之前只能使用写死的方法定义订阅方法,这样非常容易出错。真正的获取订阅方法集合的方法其实是findUsingInfo(subscriberClass)方法。

findUsingInfo的源码如下所示:

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

首先会执行prepareFindState方法去获取FindState,代码如下:

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

FIND_STATE_POOL:是一个最近使用且长度为4的FindState数组,目的是用来EventBus缓存FindState信息,提升eventBus的运行效率的。

  • FindState对象是什么?
 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;
}

开始我也有点懵逼,各种类傻傻分不清,但是我们打个断点就什么都明白了,其实FindState类就是一个保存将要查找的订阅方法信息的类。其主要成员变量如下:

  • subscriberMethods :SubScriber订阅者(对应demo中MainActivity)的所有订阅方法的集合。

  • anyMethodByEventType :一个用来保存eventType(对应demo中的EventMessage)和其对应的method。

  • subscriberClassByMethodKey :一个map对象,key是一个订阅方法名称和EventType参数构成的字符串,value为订阅方法的class对象。

  • subscriberClass和class:订阅者类的class字节码对象

  • 如何获取subscriber的订阅方法?

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

subscriberInfoIndexes 不为空会调用getSubscriberInfo方法获取SubscriberInfo对象,SubscriberInfo对象包括了Subscriber和订阅方法的信息。后面我们发现SubscriberInfo是通过index.getSubscriberInfo()方法来得到的。那么index指的是什么呢?

3.0版本中,EventBus提供了一个EventBusAnnotationProcessor注解处理器来在编译期通过读取@Subscribe()注解并解析,
处理其中所包含的信息,然后生成java类来保存所有订阅者关于订阅的信息,这样就比在运行时使用反射来获得这些订阅者的
信息速度要快.我们可以参考EventBus项目里的EventBusPerformance这个例子,编译后我们可以在build文件夹里找到这个类MyEventBusIndex 类,前面的index就属于MyEventBusIndex对象类型

建议用git拉下EventBus的源码,然后搜索EventBusAnnotationProcessor这个类,其源码比较多,这里我们看看它的createInfoIndexFile方法,其源码如下所示:

  private void createInfoIndexFile(String index) {
        BufferedWriter writer = null;
        try {
            JavaFileObject sourceFile = processingEnv.getFiler().createSourceFile(index);
            int period = index.lastIndexOf('.');
            String myPackage = period > 0 ? index.substring(0, period) : null;
            String clazz = index.substring(period + 1);
            writer = new BufferedWriter(sourceFile.openWriter());
            if (myPackage != null) {
                writer.write("package " + myPackage + ";\n\n");
            }
            writer.write("import org.greenrobot.eventbus.meta.SimpleSubscriberInfo;\n");
            writer.write("import org.greenrobot.eventbus.meta.SubscriberMethodInfo;\n");
            writer.write("import org.greenrobot.eventbus.meta.SubscriberInfo;\n");
            writer.write("import org.greenrobot.eventbus.meta.SubscriberInfoIndex;\n\n");
            writer.write("import org.greenrobot.eventbus.ThreadMode;\n\n");
            writer.write("import java.util.HashMap;\n");
            writer.write("import java.util.Map;\n\n");
            writer.write("/** This class is generated by EventBus, do not edit. */\n");
            writer.write("public class " + clazz + " implements SubscriberInfoIndex {\n");
            writer.write("    private static final Map<Class<?>, SubscriberInfo> SUBSCRIBER_INDEX;\n\n");
            writer.write("    static {\n");
            writer.write("        SUBSCRIBER_INDEX = new HashMap<Class<?>, SubscriberInfo>();\n\n");
         
            writeIndexLines(writer, myPackage);//把用了Subscriber注解的方法和方法所在的类信息拼凑起来
            writer.write("    }\n\n");
            writer.write("    private static void putIndex(SubscriberInfo info) {\n");
            writer.write("        SUBSCRIBER_INDEX.put(info.getSubscriberClass(), info);\n");
            writer.write("    }\n\n");
            writer.write("    @Override\n");
            writer.write("    public SubscriberInfo getSubscriberInfo(Class<?> subscriberClass) {\n");
            writer.write("        SubscriberInfo info = SUBSCRIBER_INDEX.get(subscriberClass);\n");
            writer.write("        if (info != null) {\n");
            writer.write("            return info;\n");
            writer.write("        } else {\n");
            writer.write("            return null;\n");
            writer.write("        }\n");
            writer.write("    }\n");
            writer.write("}\n");
        } catch (IOException e) {
            throw new RuntimeException("Could not write source for " + index, e);
        } finally {
            if (writer != null) {
                try {
                    writer.close();
                } catch (IOException e) {
                    //Silent
                }
            }
        }
    }

createInfoIndexFile方法其实就是在创建一个MyEventBusIndex.class文件,其中writeIndexLines方法是在把用了Subscriber注解的方法和方法所在的类信息拼凑起来,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");
            }
        }
    }

下面再来看看EventBusAnnotationProcessor注解处理类生成的MyEventBusIndex这个类都长什么样吧,可以通过build EventBusPerformance这个model来生成它。

public class MyEventBusIndex implements SubscriberInfoIndex {
    private static final Map<Class<?>, SubscriberInfo> SUBSCRIBER_INDEX;

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

        putIndex(new SimpleSubscriberInfo(org.greenrobot.eventbusperf.testsubject.PerfTestEventBus.SubscribeClassEventBusMainOrdered.class,
                true, new SubscriberMethodInfo[] {
            new SubscriberMethodInfo("onEvent", TestEvent.class, ThreadMode.MAIN_ORDERED),
        }));

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

        putIndex(new SimpleSubscriberInfo(org.greenrobot.eventbusperf.testsubject.PerfTestEventBus.SubscribeClassEventBusBackground.class,
                true, new SubscriberMethodInfo[] {
            new SubscriberMethodInfo("onEventBackgroundThread", TestEvent.class, ThreadMode.BACKGROUND),
        }));

        putIndex(new SimpleSubscriberInfo(org.greenrobot.eventbusperf.testsubject.PerfTestEventBus.SubscribeClassEventBusMain.class,
                true, new SubscriberMethodInfo[] {
            new SubscriberMethodInfo("onEventMainThread", TestEvent.class, ThreadMode.MAIN),
        }));

        putIndex(new SimpleSubscriberInfo(org.greenrobot.eventbusperf.testsubject.SubscribeClassEventBusDefault.class,
                true, new SubscriberMethodInfo[] {
            new SubscriberMethodInfo("onEvent", TestEvent.class),
        }));

        putIndex(new SimpleSubscriberInfo(org.greenrobot.eventbusperf.testsubject.PerfTestEventBus.SubscriberClassEventBusAsync.class,
                true, new SubscriberMethodInfo[] {
            new SubscriberMethodInfo("onEventAsync", TestEvent.class, ThreadMode.ASYNC),
        }));

    }

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

可以看出MyEventBusIndex这个类已经把我们定义的订阅方法信息全都用一个map保存起来了,key为Subscriber的字节码类,value为订阅方法信息类。后面也就不奇怪,我们可以通过迭代直接得到订阅方法的信息了。

如果EventBus没有拿到MyEventBusIndex对象携带的订阅方法信息的话,那么将通过Subscriber对象手动解析带有@subscribe注解的订阅方法,当然这种方法效率太低了,其实是一种容错处理。这个解析过程便是通过findUsingReflectionInSingleClass实现的,如下所示:

  private void findUsingReflectionInSingleClass(FindState findState) {
        Method[] methods;
        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;
        }
        for (Method method : methods) {
            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");
            }
        }
    }

  • 订阅方法注册过程

前面我们拿到了订阅方法以及订阅对象的信息后,并保持在SubscriberMethod集合中,后面会迭代这个集合,然后依次执行subscribe方法。subscribe方法的源码如下所示:

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

subscribe()方法其实主要就干了这么几件事:

  • 对消息进行优先级排序

  • 缓存subscriber method的信息
    subscriptionsByEventType这个Map对象的值就是用来缓存订阅方法的信息的,其中key为EventType的class对象,value为Subscription对象的集合,而Subscription对象的成员变量就是订阅者对象Subscriber以及订阅方法SubscriberMethod,这个map对象在后面发送消息时会用到,当要发送消息时,其实就是迭代这个对象,然后利用发射执行订阅方法。

  • 如果有sticky消息,直接发送。也可以得知sticky消息在注册后是可以
    执行的。

整个注册的大致流程如下:

eventbus注册流程.png

(2)发送消息和接收消息

由于sticky消息的发送最终也是执行post方法,这里只拿post方法来做分析,EventBus的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;
            }
        }
    }

这个方法主要用来,判断消息是否已经发送,方法执行到底是否在主线程中,消息是否已经取消,并且用EventType保存了如果符合要求,则程序继续往下执行postSingleEvent方法,然后是各种判断,接着会执行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,并迭代这个Map对象,取出订阅方法的信息,并最终执行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的值,判断方法在哪个线程中执行,无论是在主线程还是子线程中执行,最终都会invokeSubscriber方法,其实就是利用发射执行Subscriber method,所以EventBus的post()方法执行后,最终会执行Subscriber method。

  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);
        }
    }
  • POSTING:Subscriber和Subscriber Method在同一个线程中执行

  • MAIN:Subscriber Method将在主线程中执行,如果在主线程中直接执行Subscriber Method,如果在子线程中使用handler进行消息发送,并在主线程中执行。

  • MAIN_ORDERED:主线程中按顺序执行Subscriber Method。

  • BACKGROUND:如果post方法发送消息在子线程中,那么直接执行Subscriber method;如果post方法发送消息是在主线程中,将会在子线程中执行Subscriber method。

  • ASYNC:无论是在主线程还是子线程中发送消息,那么都讲会子线程中执行Subscriber method


    EventBus发送消息的过程.png

(3) EventBus unRegister过程

unregister方法的源码如下:

 /** Unregisters the given subscriber from all event classes. */
    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());
        }
    }

把之前Subscriber注册时保存下来的订阅方法信息删除,然后执行
unsubscribeByEventType方法,其代码如下所示:

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

循环查找subScription对象并把它的active属性改成false,最后删除subscription对象。

---------------end-----------------

如果文章对你有帮助的话,记得点一个赞哦。

相关文章

网友评论

    本文标题:EventBus源码解析

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