源码解析:EventBus

130 阅读1分钟
通过apt在编译期将所有被 @Subscribe注解的函数添加到MyEventBusIndex对象中。

在register过程中生成subscriptionsByEventType的数据。

在 post过程中通过subscriptionsByEventType数据查找对应的函数,然后再通过反射的方式调用。

1,普通post事件 : 直接发送

public void post(Object event) {

    postSingleEventForEventType(event, event.getClass());

}

//遍历所有的订阅者,发送对应的事件

private void postSingleEventForEventType(Object event, Class<?> eventClass) {

    CopyOnWriteArrayList<Subscription> subscriptions;

    //获取eventBean对应的多个Subscribe事件

    synchronized (this) {

        subscriptions = subscriptionsByEventType.get(eventClass);

    }

    if (subscriptions != null && !subscriptions.isEmpty()) {

        for (Subscription subscription : subscriptions) {

            //发送普通事件的时候不触发粘性事件

            if (!subscription.subscriberMethod.isSticky()) {

                postToSubscription(subscription, event);

            }

        }

    }

}

//发送事件,主线程和异步

private void postToSubscription(final Subscription subscription, final Object event) {

    switch (subscription.subscriberMethod.getThreadMode()) {

        case POSTING: // 订阅、发布在同一线程

            invokeSubscriber(subscription, event);

            break;

        case MAIN:

            //事件发送方是主线程

            if (Looper.myLooper() == Looper.getMainLooper()) {

                invokeSubscriber(subscription, event);

            } else {

                //事件发送方是子线程

                handler.post(new Runnable() {

                    @Override

                    public void run() {

                        invokeSubscriber(subscription, event);

                    }

                });

            }

            break;

        case ASYNC:

            //发送方在主线程

            if (Looper.myLooper() == Looper.getMainLooper()) {

                executorService.execute(new Runnable() {

                    @Override

                    public void run() {

                        invokeSubscriber(subscription, event);

                    }

                });

            } else {

                invokeSubscriber(subscription, event);

            }

            break;

    }

}

//反射调用apt获取的方法

private void invokeSubscriber(Subscription subscription, Object event) {

    try {

        subscription.subscriberMethod.getMethod().invoke(subscription.subscriber, event);

    } catch (Exception e) {

        e.printStackTrace();

    }

}

2,粘性事件 : 注册的时候发送

普通事件是先注册,后发送。而粘性事件相反,是先发送存数据,后注册的时候调函数。

如跳转activity传递参数

public void postSticky(Object event) {

    stickyEvents.put(event.getClass(), event);

}

/**

 * 订阅者的入口

 *

 * @param subscriber activity,fragment

 */

public void register(Object subscriber) {

    Class<?> subscriberClass = subscriber.getClass();

    List<SubscriberMethod> subscriberMethods = findSubscriberMethods(subscriberClass);

    for (SubscriberMethod method : subscriberMethods) {

        subscribe(subscriber, method);

    }

}

private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {

        Class<?> eventType = subscriberMethod.getEventType();

        CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType);

        if (subscriptions == null) {

            subscriptions = new CopyOnWriteArrayList<>();

            subscriptionsByEventType.put(eventType, subscriptions);

        }

        Subscription subscription = new Subscription(subscriber, subscriberMethod);

//        if (subscriptions.contains(subscription)) {

//            //粘性事件相关逻辑

//            sticky(subscriberMethod, eventType, subscription);

//            return;

//        }

        //根据优先级插队

        int size = subscriptions.size();

        for (int i = 0; i <= size; i++) {

            if (i == size || subscriberMethod.getPriority() > subscriptions.get(i).subscriberMethod.getPriority()) {

                if (!subscriptions.contains(subscription)) subscriptions.add(i, subscription);

                break;

            }

        }

        //订阅者类型集合

        List<Class<?>> subscribeEvents = typeBySubscriber.get(subscriber);

        if (subscribeEvents == null) {

            subscribeEvents = new ArrayList<>();

            typeBySubscriber.put(subscriber, subscribeEvents);

        }

        subscribeEvents.add(eventType);

        //粘性事件入口

        sticky(subscriberMethod, eventType, subscription);

    }

    /**

     * 在register的时候,遍历当前类下所有Subscribe函数,查看是否有粘性事件

     */

    private void sticky(SubscriberMethod subscriberMethod, Class<?> eventType, Subscription subscription) {

        if (subscriberMethod.isSticky()) {

            Object event = stickyEvents.get(eventType);

            if (event != null) {

                postToSubscription(subscription, event);

            }

        }

}