解读EventBus源码

Event

其实就是一个对象,可以是网络请求返回的字符串,也可以是某个开关状态等等。事件类型(EventType)指事件所属的 Class。
事件分为一般事件和 Sticky 事件,相对于一般事件,Sticky 事件不同之处在于,当事件发布后,再有订阅者开始订阅该类型事件,依然能收到该类型事件最近一个 Sticky 事件

ThreadMode

  • PostThread-> onEvent(Object e)
    表示此方法在事件发布的线程中执行,如果是在主线程中发布则在主线程中执行,并且不能进行耗时操作以避免阻塞主线程;如果在子线程中发布则在子线程中执行。
  • MainThread-> onEventMainThread(Object e)
    表示此方法在UI线程中执行,不能进行耗时操作避免阻塞主线程。
  • BackgroundThread-> onEventBackgroundThread(Object e)
    表示此方法不在UI线程中执行,如果在UI线程中发布,则在子线程中执行,如果在子线程中发布,则在该子线程中执行。
  • Async-> onEventAsync(Object e)
    表示此方法加入到后台线程池中调用

EventBusBuilder

创建EventBus的类,可以自定义配置,也可以使用默认配置,EventBusBuilder属于创建者模式

EventBus

EventBus.getDefault()是单例模式的体现

/** Convenience singleton for apps using a process-wide EventBus instance. */
static volatile EventBus defaultInstance;
public static EventBus getDefault() {
    if (defaultInstance == null) {
        synchronized (EventBus.class) {
            if (defaultInstance == null) {
                defaultInstance = new EventBus();
            }
        }
    }
    return defaultInstance;
}

公布了四个方法供订阅者订阅,如果订阅者对订阅的事件不感兴趣了,必须调用unregister方法取消注册。
布尔型参数sticky表示是否对最近的一次已发送的事件感兴趣,需要使用postSticky(Object)发送Sticky事件

//subscriber为订阅者
public void register(Object subscriber) {
    register(subscriber, false, 0);
}
//subscriber为订阅者,priority为优先级
public void register(Object subscriber, int priority) {
    register(subscriber, false, priority);
}
//subscriber为订阅者
public void registerSticky(Object subscriber) {
    register(subscriber, true, 0);
}
//subscriber为订阅者,priority为优先级
public void registerSticky(Object subscriber, int priority) {
    register(subscriber, true, priority);
}

其本质是调用了一个私有方法

private synchronized void register(Object subscriber, boolean sticky, int priority) {
        //去寻找订阅者的事件处理方法
    List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriber.getClass());
        //遍历返回值进行subscribe
    for (SubscriberMethod subscriberMethod : subscriberMethods) {
        subscribe(subscriber, subscriberMethod, sticky, priority);
    }
}

通过SubscriberMethodFinder的findSubscriberMethods方法,将订阅者传入,返回的是一个List,里面存储了一系列的SubscriberMethod,该方法的作用就是去订阅者的类中寻找订阅的事件处理函数

List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
    String key = subscriberClass.getName();//获得订阅者的name
    List<SubscriberMethod> subscriberMethods;//用于存储返回结果
    synchronized (methodCache) {
                //首先从缓存中查找,存储它的是一个HashMap<String, List<SubscriberMethod>>
        subscriberMethods = methodCache.get(key);
    }
    if (subscriberMethods != null) {
                //如果在缓存中找到了,则直接返回
        return subscriberMethods;
    }
        //如果在缓存中没有找到,则新建一个ArrayList用于存储后期找到的SubscriberMethod
    subscriberMethods = new ArrayList<SubscriberMethod>();
        //将订阅者赋值给Class对象clazz
    Class<?> clazz = subscriberClass;
        //用于判断方法是否已添加过
    HashSet<String> eventTypesFound = new HashSet<String>();
    StringBuilder methodKeyBuilder = new StringBuilder();
        //开始查找
    while (clazz != null) {
                //获得类的全名
        String name = clazz.getName();
                //如果是系统的类则直接跳过查找(以java,javax,android开头)
        if (name.startsWith("java.") || name.startsWith("javax.") || name.startsWith("android.")) {
            // Skip system classes, this just degrades performance
            break;
        }

        // Starting with EventBus 2.2 we enforced methods to be public (might change with annotations again)
                //从EventBus 2.2开始要求方法必须是公有的
                //获得所有可以访问的方法
        Method[] methods = clazz.getDeclaredMethods();
                //遍历方法
        for (Method method : methods) {
                        //获得方法名
            String methodName = method.getName();
                        //如果方法名是以onEvent开头
            if (methodName.startsWith(ON_EVENT_METHOD_NAME)) {
                                //获得该方法的修饰符对应的值
                int modifiers = method.getModifiers();
                                //如果该方法是共有的,并且不是抽象的,不是静态的,不是同步方法等
                if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) {
                                        //获得该方法的参数
                    Class<?>[] parameterTypes = method.getParameterTypes();
                                        //如果参数只有一个则继续执行
                    if (parameterTypes.length == 1) {
                        String modifierString = methodName.substring(ON_EVENT_METHOD_NAME.length());
                        ThreadMode threadMode;
                                                //根据方法名判断线程模式
                        if (modifierString.length() == 0) {
                                                        //如果是方法名是onEvent,则线程模式为PostThread
                            threadMode = ThreadMode.PostThread;
                        } else if (modifierString.equals("MainThread")) {
                                                        //如果是方法名是onEventMainThread,则线程模式为MainThread
                            threadMode = ThreadMode.MainThread;
                        } else if (modifierString.equals("BackgroundThread")) {
                                                        //如果是方法名是onEventBackgroundThread,则线程模式为BackgroundThread
                            threadMode = ThreadMode.BackgroundThread;
                        } else if (modifierString.equals("Async")) {
                                                        //如果是方法名是onEventAsync,则线程模式为Async
                            threadMode = ThreadMode.Async;
                        } else {
                                                        //其他则跳过
                            if (skipMethodVerificationForClasses.containsKey(clazz)) {
                                continue;
                            } else {
                                throw new EventBusException("Illegal onEvent method, check for typos: " + method);
                            }
                        }
                                                //获得参数
                        Class<?> eventType = parameterTypes[0];
                                                //构造方法键值,值为:方法名->参数类型名
                        methodKeyBuilder.setLength(0);
                        methodKeyBuilder.append(methodName);
                        methodKeyBuilder.append('>').append(eventType.getName());
                        String methodKey = methodKeyBuilder.toString();
                        if (eventTypesFound.add(methodKey)) {
                            // Only add if not already found in a sub class
                                                        //添加到返回的subscriberMethods中,在没有add的情况下,eventTypesFound.add()方法会返回true,否则返回false,避免重复添加
                            subscriberMethods.add(new SubscriberMethod(method, threadMode, eventType));
                        }
                    }
                                //如果方法不满足条件则直接跳过
                } else if (!skipMethodVerificationForClasses.containsKey(clazz)) {
                                        //不在忽略列表则会打印这条日志
                    Log.d(EventBus.TAG, "Skipping method (not public, static or abstract): " + clazz + "."
                            + methodName);
                }
            }
        }
                //获得父类,继续查找
        clazz = clazz.getSuperclass();
    }
        //如果没有找到事件处理方法,则抛出异常
    if (subscriberMethods.isEmpty()) {
        throw new EventBusException("Subscriber " + subscriberClass + " has no public methods called "
                + ON_EVENT_METHOD_NAME);
    } else {
                //否则,先加入到缓存中去,再返回
        synchronized (methodCache) {
            methodCache.put(key, subscriberMethods);
        }
        return subscriberMethods;
    }
}

SubscriberMethod类里存储了以下几个变量

final Method method;//方法名
final ThreadMode threadMode;//线程模式
final Class<?> eventType;//方法参数,即事件类型

Subscription类里存储了以下几个变量

final Object subscriber;//订阅者
final SubscriberMethod subscriberMethod;//SubscriberMethod对象
final int priority;//优先级

我们再去看看subscribe方法

// Must be called in synchronized block
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod, boolean sticky, int priority) {
        //获得事件处理函数的参数,即事件类型
    Class<?> eventType = subscriberMethod.eventType;
        //去subscriptionsByEventType查找CopyOnWriteArrayList<Subscription>对象
    CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
        //创建Subscription 对象
    Subscription newSubscription = new Subscription(subscriber, subscriberMethod, priority);
    if (subscriptions == null) {
                //如果没有则创建一个,并将subscriptions存入subscriptionsByEventType中去
        subscriptions = new CopyOnWriteArrayList<Subscription>();
        subscriptionsByEventType.put(eventType, subscriptions);
    } else {
                //如果找到了,并且里面已经包含了newSubscription,则扔出一个已经注册的异常
        if (subscriptions.contains(newSubscription)) {
            throw new EventBusException("Subscriber " + subscriber.getClass() + " already registered to event "
                    + eventType);
        }
    }

    // Starting with EventBus 2.2 we enforced methods to be public (might change with annotations again)
    // subscriberMethod.method.setAccessible(true);
        //找到合适的位置加入newSubscription,其实质是按优先级添加
    int size = subscriptions.size();
    for (int i = 0; i <= size; i++) {
        if (i == size || newSubscription.priority > subscriptions.get(i).priority) {
            subscriptions.add(i, newSubscription);
            break;
        }
    }
        //获得订阅者的所有订阅事件的集合
        //typesBySubscriber 是一个Map对象,Map<Object, List<Class<?>>> typesBySubscriber;里面存储了对应订阅者的所订阅的所有事件
    List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);
    if (subscribedEvents == null) {
                //如果为空,则创建一个并将并将创建的对象加入到typesBySubscriber中区
        subscribedEvents = new ArrayList<Class<?>>();
        typesBySubscriber.put(subscriber, subscribedEvents);
    }
        //将事件参数加入到subscribedEvents中去
    subscribedEvents.add(eventType);
        //如果是sticky的,则
    if (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)) {
                                         //根据eventType查找stickyEvents,如果有则立即去执行事件
                    Object stickyEvent = entry.getValue();
                    checkPostStickyEventToSubscription(newSubscription, stickyEvent);
                }
            }
        } else {
                        //根据eventType查找stickyEvents,如果有则立即去执行事件
            Object stickyEvent = stickyEvents.get(eventType);
            checkPostStickyEventToSubscription(newSubscription, stickyEvent);
        }
    }
}

总结一下就是:
把匹配的方法保存在一个Map中,即subscriptionsByEventType,根据变量名可知是根据事件类型查找Subscriptions
key:eventType 订阅事件的参数的Class对象
value:CopyOnWriteArrayList;
Subscription中则保存着subscriber, subscriberMethod(method, threadMode, eventType), priority;

以上内容,EventBus为我们完成了所有方法的存储,那么是如何取消注册的呢,很简单,从对应的变量里移除即可

    /** 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) {
                //调用unubscribeByEventType方法移除对应的值
                unubscribeByEventType(subscriber, eventType);
            }
            //从typesBySubscriber移除订阅者
            typesBySubscriber.remove(subscriber);
        } else {
            //之前没订阅
            Log.w(TAG, "Subscriber to unregister was not registered before: " + subscriber.getClass());
        }
    }
    /** Only updates subscriptionsByEventType, not typesBySubscriber! Caller must update typesBySubscriber. */
    private void unubscribeByEventType(Object subscriber, Class<?> eventType) {
        //根据订阅的事件类型查找Subscription的集合
        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);
                //如果与subscription中的订阅者等于传进来的订阅者,则移除
                if (subscription.subscriber == subscriber) {
                    subscription.active = false;
                    subscriptions.remove(i);
                    i--;
                    size--;
                }
            }
        }
    }

关于EventBus如何处理我们的订阅事件,理论上应该是从subscriptionsByEventType中取对应的方法,通过反射来调用,我们来看看post相关的方法。

//包含一个eventQueue和一些标识,如是否主线程等
final static class PostingThreadState {
    final List<Object> eventQueue = new ArrayList<Object>();
    boolean isPosting;
    boolean isMainThread;
    Subscription subscription;
    Object event;
    boolean canceled;
}
//一个ThreadLocal对象,保存当前线程的PostingThreadState对象
private final ThreadLocal<PostingThreadState> currentPostingThreadState = new ThreadLocal<PostingThreadState>() {
    @Override
    protected PostingThreadState initialValue() {
        return new PostingThreadState();
    }
};
/** Posts the given event to the event bus. */
public void post(Object event) {
        //拿到当前线程的PostingThreadState 
    PostingThreadState postingState = currentPostingThreadState.get();
        //拿到事件队列
    List<Object> eventQueue = postingState.eventQueue;
        //将要发送的事件加入到事件队列中区
    eventQueue.add(event);
        //如果不在发送事件
    if (!postingState.isPosting) {
                //判断当前线程是不是UI线程
        postingState.isMainThread = Looper.getMainLooper() == Looper.myLooper();
                //是否在发送事件
        postingState.isPosting = true;
                //如果取消了则扔出异常
        if (postingState.canceled) {
            throw new EventBusException("Internal error. Abort state was not reset");
        }
                //事件队列不为空时,循环队列,调用postSingleEvent方法进行处理
        try {
            while (!eventQueue.isEmpty()) {
                postSingleEvent(eventQueue.remove(0), postingState);
            }
        } finally {
                        //复位
            postingState.isPosting = false;
            postingState.isMainThread = false;
        }
    }
}

/**
 * Posts the given event to the event bus and holds on to the event (because it is sticky). The most recent sticky
 * event of an event's type is kept in memory for future access. This can be {@link #registerSticky(Object)} or
 * {@link #getStickyEvent(Class)}.
 */
//对于Sticky事件,会将其先保存,再调用post方法发送事件,保存后的事件为之后订阅Sticky的类提供最近一次的Sticky事件,移除事件则在removeStickyEvent方法中完成
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);
}
private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {
        //得到事件类型
    Class<?> eventClass = event.getClass();
    boolean subscriptionFound = false;
        //如果具有继承性则查找父类,包括接口
    if (eventInheritance) {
                //查找所有满足条件的eventTypes 
        List<Class<?>> eventTypes = lookupAllEventTypes(eventClass);
        int countTypes = eventTypes.size();
                //遍历调用postSingleEventForEventType
        for (int h = 0; h < countTypes; h++) {
            Class<?> clazz = eventTypes.get(h);
            subscriptionFound |= postSingleEventForEventType(event, postingState, clazz);
        }
    } else {
                //否则直接调用postSingleEventForEventType
        subscriptionFound = postSingleEventForEventType(event, postingState, eventClass);
    }
    if (!subscriptionFound) {
                //如果没有找到订阅者,则扔出异常
        if (logNoSubscriberMessages) {
            Log.d(TAG, "No subscribers registered for event " + eventClass);
        }
        if (sendNoSubscriberEvent && eventClass != NoSubscriberEvent.class &&
                eventClass != SubscriberExceptionEvent.class) {
            post(new NoSubscriberEvent(this, event));
        }
    }
}
private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class<?> eventClass) {
    CopyOnWriteArrayList<Subscription> subscriptions;
    synchronized (this) {
                //拿到subscriptions 
        subscriptions = subscriptionsByEventType.get(eventClass);
    }
        //不为空的情况下遍历
    if (subscriptions != null && !subscriptions.isEmpty()) {
        for (Subscription subscription : subscriptions) {
            postingState.event = event;
            postingState.subscription = subscription;
            boolean aborted = false;
            try {
                                //调用postToSubscription方法处理
                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;
}
//根据线程模式进行分发,本质是反射调用
private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {
    switch (subscription.subscriberMethod.threadMode) {
        case PostThread:
                        //在当前线程中直接反射调用
            invokeSubscriber(subscription, event);
            break;
        case MainThread:
            if (isMainThread) {
                                //如果当前线程是主函数,则直接反射调用
                invokeSubscriber(subscription, event);
            } else {
                                //否则加入到队列中去,在handler的handleMessage中处理
                mainThreadPoster.enqueue(subscription, event);
            }
            break;
        case BackgroundThread:
            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);
    }
}

最终可以概括为两张图

这里写图片描述

这里写图片描述

PendingPost

订阅者和事件相关的类,内部实现了缓存不用的对象

PendingPostQueue

内部维护了一个队列,HandlerPoster、AsyncPoster、BackgroundPoster处理时从队列中取出一个元素进行处理

HandlerPoster

事件主线程处理,对应ThreadMode.MainThread。继承自 Handler,enqueue 函数将事件放到队列中,并利用 handler 发送 message,handleMessage 函数从队列中取事件,invoke 事件响应函数处理。

AsyncPoster

事件异步线程处理,对应ThreadMode.Async,继承自 Runnable。enqueue 函数将事件放到队列中,并调用线程池执行当前任务,在 run 函数从队列中取事件,invoke 事件响应函数处理。

BackgroundPoster

事件 Background 处理,对应ThreadMode.BackgroundThread,继承自 Runnable。enqueue 函数将事件放到队列中,并调用线程池执行当前任务,在 run 函数从队列中取事件,invoke 事件响应函数处理。与 AsyncPoster.java 不同的是,BackgroundPoster中的任务只在同一个线程中依次执行,而不是并发执行。

参考链接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值