EventBus代码分析

简介

EventBus是一种可用于Android或者Java程序的发布/订阅事件总线。它能简化Activities, Fragments, Threads, Services等组件之间的通信。用更少的代码,达到更高的质量。
它有很多优点:
简化应用组件间的通信;
解耦事件的发送者和接收者;
避免复杂和容易出错的依赖和生命周期的问题;
很快,专门为高性能优化过等等。

使用方法

image
  • 创建事件
    EventBus3.0以后,创建的事件可以是任何类。
public static class MessageEvent { 
    /* Additional fields if needed */ 
}
  • 订阅者准备事件处理函数
    EventBus3.0以后,事件处理函数的函数名可以任意命名,但是函数必须用Subscribe注释,还可以在Subscribe注释中指定ThreadMode,priority,sticky。
    ThreadMode 表示事件的处理方式,是同步还是异步处理,是在发布者同一线程还是另起一个线程。
    priority表示优先级,priority值越大越推后执行。
    sticky表示本事件处理函数可以用于处理sticky事件,在订阅者注册的时候,sticky事件会被投递给订阅者处理。
@Subscribe(threadMode = ThreadMode.MAIN)  
public void onMessageEvent(MessageEvent event) {
    /* Do something */
};
  • 订阅者注册
 @Override
 public void onStart() {
     super.onStart();
     EventBus.getDefault().register(this);
 }

 @Override
 public void onStop() {
     super.onStop();
     EventBus.getDefault().unregister(this);
 }
  • 发布者post事件
EventBus.getDefault().post(new MessageEvent());

代码流程分析

  • EventBus单件模式
    EventBus实例在单个进程内是独一无二的,每个线程都可以引用。
    public static EventBus getDefault() {
        EventBus instance = defaultInstance;
        if (instance == null) {
            synchronized (EventBus.class) {
                instance = EventBus.defaultInstance;
                if (instance == null) {
                    instance = EventBus.defaultInstance = new EventBus();
                }
            }
        }
        return instance;
    }
  • 注册流程
    public void register(Object subscriber) {
        Class subscriberClass = subscriber.getClass();
        List subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
        synchronized (this) {
            for (SubscriberMethod subscriberMethod : subscriberMethods) {
                subscribe(subscriber, subscriberMethod);
            }
        }
    }

注册函数首先调用subscriberMethodFinder.findSubscriberMethods(subscriberClass) 来取得这个类所有的事件处理函数。
然后对每个SubscriberMethod ,循环调用subscribe。

subscribe函数主要完成三件事:

  1. 把新的Subscription添加到对应eventType的Subscription列表中 subscriptionsByEventType
  2. 把eventType添加到对应subscriber的subscribedEvents列表中 typesBySubscriber
  3. 如果订阅者的事件处理函数有sticky标记的,则把系统中对应的sticky事件派发给订阅者
    private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
        Class eventType = subscriberMethod.eventType;
        Subscription newSubscription = new Subscription(subscriber, subscriberMethod);

         //1 把新的Subscription添加到对应eventType的Subscription列表中
        CopyOnWriteArrayList 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;
            }
        }


        //2  把eventType添加到对应subscriber的subscribedEvents列表中
        List> subscribedEvents = typesBySubscriber.get(subscriber);
        if (subscribedEvents == null) {
            subscribedEvents = new ArrayList<>();
            typesBySubscriber.put(subscriber, subscribedEvents);
        }
        subscribedEvents.add(eventType);

        //3 把系统中对应的sticky事件派发给订阅者
        if (subscriberMethod.sticky) {
            if (eventInheritance) {//如果eventInheritance true  即事件处理函数会处理事件及派生类事件
                // 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).
                Set, Object>> entries = stickyEvents.entrySet();
                for (Map.Entry, Object> entry : entries) {
                    Class candidateEventType = entry.getKey();
                    if (eventType.isAssignableFrom(candidateEventType)) {
                        Object stickyEvent = entry.getValue();
                        checkPostStickyEventToSubscription(newSubscription, stickyEvent);
                    }
                }
            } else {//如果eventInheritance false 即事件处理函数不处理派生类事件
                Object stickyEvent = stickyEvents.get(eventType);
                checkPostStickyEventToSubscription(newSubscription, stickyEvent);
            }
        }
    }
  • post流程
    在post流程,发布者把事件派发出去,交给相应的线程,由对应的事件处理函数处理。
    post流程的主要步骤:
  1. 把事件加入发布者线程的待投递事件队列
  2. 把待投递事件队列的所有事件按照先入先出的顺序全部派发出去
    public void post(Object event) {
        PostingThreadState postingState = currentPostingThreadState.get();  //获取发布者线程的私有数据
        List 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;
            }
        }
    }
 
 

具体的派发流程在postSingleEvent中实现

    private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {
        Class eventClass = event.getClass();
        boolean subscriptionFound = false;
        if (eventInheritance) { //如果eventInheritance为true,把event事件以及父类事件全部派发
            List> 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 {//如果eventInheritance为false,只把event事件派发
            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中,把event派发给对应的订阅者

    private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class eventClass) {
        CopyOnWriteArrayList 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;
    }

真正的派发是在postToSubscription中进行的。派发时,根据事件处理函数注释中的threadMode,采取不同的派发策略。
POSTING
POSTING订阅者 ,则立即执行事件处理函数。
MAIN
MAIN订阅者,如果发布者在主线程,则立即执行事件处理函数。
如果发布者不在主线程,则派发到mainThreadPoster异步执行,但是执行线程仍然是主线程。
MAIN_ORDERED
MAIN_ORDERED订阅者,对于android平台来说,是统一派发到mainThreadPoster异步执行的。其他平台,则是立即执行。
BACKGROUND:如果发布者在主线程,则派发到backgroundPoster异步执行。backgroundPoster会把事件放到线程池中处理。如果不在主线程,则立即执行。
ASYNC:统一派发到asyncPoster中异步执行。asyncPoster会把事件放到线程池中处理。

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

你可能感兴趣的:(EventBus代码分析)