EventBus,由greenrobot组织贡献(该组织还贡献了greenDAO),一个Android事件发布/订阅轻量级框架;


进程内EventBus可以代替Android传统的Intent,Handler,Broadcast或接口函数,在Fragment,Activity,Service线程之间传递数据,执行方法;



github地址  https://github.com/greenrobot/EventBus    点击打开链接


在没有它之前,进程内通信一直都是用的广播来发送接收消息,后来用了后发现真的是太方便了,而且还是轻量级的,最近研究了下它的源码,

学习了下大神牛逼的架构和思维,确实很厉害,为啥我没想到呢。


怎么使用的就不做介绍了,相信大家都会用,下面直接进入正文


先看下源码结构,如图:

Android EventBus 源码解析_第1张图片


代码量其实不是很多,很多类里面就只有一点代码,前面3个文件目录都是一些辅助工具类,不是核心,有空可以去学习下,

这里只解析主干逻辑。



平时我们主要用这几个方法:注册订阅者,注销订阅者,定义订阅方法,post事件,所以就从这几个方面开始解析


首先我们知道EventBus用的是单例模式,整个进程中只会有一个EventBus的实例


    static volatile EventBus defaultInstance;

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


这里加上同步,防止多线程调用getDefault()时出现几个实例



接下来看下定义订阅方法


    @Subscribe(threadMode = ThreadMode.MAIN)    public void refreshUI(RefreshBagEvent event) {            }    @Subscribe    public void loadData(DataChangeEvent event) {    }

平时就是这么定义的订阅方法,为啥要这么写呢,我们先看下这个注解@Subscribe

import java.lang.annotation.Documented;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;@Documented@Retention(RetentionPolicy.RUNTIME)@Target({ElementType.METHOD})public @interface Subscribe {    /**     * 指定订阅方法所在线程     * @return     */    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;}

这个定义的注解包含了3个方法,都有默认值,订阅方法所在线程、是否开启粘性事件模式、优先级


为啥要定义这么一个注解呢?


问题先放这,后面揭晓,接下来看下注册订阅者方法register()

    /**     * Registers the given subscriber to receive events. Subscribers must call {@link #unregister(Object)} once they     * are no longer interested in receiving events.     * 

* Subscribers have event handling methods that must be annotated by {@link Subscribe}. * The {@link Subscribe} annotation also allows configuration like {@link * ThreadMode} and priority. */ public void register(Object subscriber) { Class<?> subscriberClass = subscriber.getClass(); // 获取订阅者订阅的方法 List subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass); // 加上同步block,可能同时有多处都在注册 synchronized (this) { for (SubscriberMethod subscriberMethod : subscriberMethods) { subscribe(subscriber, subscriberMethod); } } }


当前订阅者register传入进来,拿到它的Class对象,根据这个Class对象获取register的订阅方法,看下这些订阅方法如何被获取的

    private static final Map, List> METHOD_CACHE = new ConcurrentHashMap<>();

    List findSubscriberMethods(Class<?> subscriberClass) {        List 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;        }    }

可以看到调用了findUsingReflection()或者findUsingInfo(),ignoreGeneratedIndex默认是false,那么就会直接调用 findUsingReflection(),继续往下看

    private List findUsingInfo(Class<?> subscriberClass) {        FindState findState = prepareFindState();        findState.initForSubscriber(subscriberClass);        while (findState.clazz != null) {            findState.subscriberInfo = getSubscriberInfo(findState);            // 这里应该是从缓存中获取订阅的方法,不过看源码findState.subscriberInfo永远都是null,所以进不去            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 {                // 利用反射获取订阅方法储存在findState里面                findUsingReflectionInSingleClass(findState);            }            findState.moveToSuperclass();        }        // 从findState中获取订阅方法        return getMethodsAndRelease(findState);    }

    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();            // 过滤掉非public、静态的方法            if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) {                // 获取方法中参数                Class<?>[] parameterTypes = method.getParameterTypes();                // 如果只有一个参数                if (parameterTypes.length == 1) {                    // 获取方法中Subscribe注解                    Subscribe subscribeAnnotation = method.getAnnotation(Subscribe.class);                    // 方法中Subscribe注解不为null                    if (subscribeAnnotation != null) {                        Class<?> eventType = parameterTypes[0];                        // 检查findState是否添加过这个订阅方法                        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)) {                // 抛出异常,订阅的方法必须是public,不带static、abstract的                String methodName = method.getDeclaringClass().getName() + "." + method.getName();                throw new EventBusException(methodName +                        " is a illegal @Subscribe method: must be public, non-static, and non-abstract");            }        }    }

findUsingReflectionInSingleClass()反射获取订阅方法,看到这知道为啥要用注解@Subcribe了吧,因为一个类那么多方法,怎么知道哪些方法是订阅方法呢,就是用这个注解作为标识

    private List getMethodsAndRelease(FindState findState) {        List subscriberMethods = new ArrayList<>(findState.subscriberMethods);        // 回收findState的数据        findState.recycle();        synchronized (FIND_STATE_POOL) {            for (int i = 0; i < POOL_SIZE; i++) {                if (FIND_STATE_POOL[i] == null) {                    FIND_STATE_POOL[i] = findState;                    break;                }            }        }        return subscriberMethods;    }


到这里,这个订阅者的方法都以List的形式返回了,接着回到register()


    public void register(Object subscriber) {        Class<?> subscriberClass = subscriber.getClass();        // 获取订阅者订阅的方法        List subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);        // 加上同步block,可能同时有多处都在注册        synchronized (this) {            for (SubscriberMethod subscriberMethod : subscriberMethods) {                subscribe(subscriber, subscriberMethod);            }        }    }


接下来就是开始循环把这些订阅方法一个一个的注册了,看下subscribe()

    // Must be called in synchronized block    private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {        // 获取事件.class对象        Class<?> eventType = subscriberMethod.eventType;        // 创建一个含有订阅者和订阅方法的订阅实体        Subscription newSubscription = new Subscription(subscriber, subscriberMethod);        // 根据事件类型获取订阅实体集合,CopyOnWriteArrayList是线程安全的        CopyOnWriteArrayList subscriptions = subscriptionsByEventType.get(eventType);        if (subscriptions == null) {            // 如果subscriptionsByEventType还没有事件.class对象eventType相关的订阅实体集合,就new 一个            subscriptions = new CopyOnWriteArrayList<>();            subscriptionsByEventType.put(eventType, subscriptions);        } else {            // 如果subscriptionsByEventType有eventType相关的订阅实体集合,且包含newSubscription,抛出异常已经注册过了            if (subscriptions.contains(newSubscription)) {                throw new EventBusException("Subscriber " + subscriber.getClass() + " already registered to event "                        + eventType);            }        }        // 把newSubscription添加到subscriptions集合中,默认优先级的情况下添加到末尾;优先级越大添加越靠前        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;            }        }        // typesBySubscriber用于判断是否注册过某个订阅者        List> subscribedEvents = typesBySubscriber.get(subscriber);        if (subscribedEvents == null) {            subscribedEvents = new ArrayList<>();            typesBySubscriber.put(subscriber, subscribedEvents);        }        subscribedEvents.add(eventType);        // sticky默认false        if (subscriberMethod.sticky) {            // eventInheritance 默认为true            // 如果eventType代表的类或者接口是candidateEventType代表的类或者接口或者父类父接口,也要post事件            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).                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 {                Object stickyEvent = stickyEvents.get(eventType);                checkPostStickyEventToSubscription(newSubscription, stickyEvent);            }        }    }

这个方法还挺长的,解析我都写在代码里面了,逻辑还是挺复杂的

    /**     * 储存事件及父类父接口Class对象;     * key:事件Class对象,value:事件及父类父接口Class对象     */    private static final Map, List>> eventTypesCache = new HashMap<>();    /**     * 储存事件及对应方法;     * key是事件的Class对象,value是订阅者及订阅的方法集合     */    private final Map, CopyOnWriteArrayList> subscriptionsByEventType;    /**     * 储存订阅者及事件Class对象;     * 用于判断订阅者是否注册过     */    private final Map>> typesBySubscriber;    /**     * 存储粘性事件;     * 用于postSticky()     */    private final Map, Object> stickyEvents;    private final ThreadLocal currentPostingThreadState = new ThreadLocal() {        @Override        protected PostingThreadState initialValue() {            // 初始化一个PostingThreadState对象            return new PostingThreadState();        }    };

跟EventBus这个类的这几个成员变量有关,这几个集合的作用主要是用来存储,具体什么作用我都解释了,这个订阅方法的核心

把事件和订阅者相关的方法存储在subscriptionsByEventType 里面,因为一个事件可能在很多地方都注册过,最后还有一个粘性事件

sticky的处理,什么是粘性事件,比如这个事件在A页面发送完毕了,一般情况下注册过的地方就会马上接受到这个事件处理掉,

然后打开过注册了这个事件的B页面的时候,是不会再接受到这个事件的,而粘性事件就相反,打开B页面同样会接受到这个事件,

可以看下源码

// sticky默认false        if (subscriberMethod.sticky) {            // eventInheritance 默认为true            // 如果eventType代表的类或者接口是candidateEventType代表的类或者接口或者父类父接口,也要post事件            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).                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 {                Object stickyEvent = stickyEvents.get(eventType);                checkPostStickyEventToSubscription(newSubscription, stickyEvent);            }        }
    private void checkPostStickyEventToSubscription(Subscription newSubscription, Object stickyEvent) {        if (stickyEvent != null) {            // If the subscriber is trying to abort the event, it will fail (event is not tracked in posting state)            // --> Strange corner case, which we don't take care of here.            postToSubscription(newSubscription, stickyEvent, isMainThread());        }    }


这里才刚开始注册事件,就调用了postToSubscription()去发布事件,postToSubscription()就是post事件的方法,这个方法后面会讲到,到这里注册就算解析完了,估计客观们都晕了,哈哈,我就用一句话概括下:

注册事件其实就是用一个HashMap   subscriptionsByEventType 把事件和注册了事件相关的类和方法储存起来,方便后面post(事件)使用。


接下来看下post()方法,


    private final ThreadLocal currentPostingThreadState = new ThreadLocal() {        @Override        protected PostingThreadState initialValue() {            // 初始化一个PostingThreadState对象            return new PostingThreadState();        }    };

    /** Posts the given event to the event bus. */    public void post(Object event) {        PostingThreadState postingState = currentPostingThreadState.get();        List eventQueue = postingState.eventQueue;        // 添加事件event对象        eventQueue.add(event);        // 状态是否为posting,如果没有,则开启        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()) {                    // 循环开始post事件,每post一个事件,就从eventQueue中移除一个事件对象                    postSingleEvent(eventQueue.remove(0), postingState);                }            } finally {                // 最终恢复默认值                postingState.isPosting = false;                postingState.isMainThread = false;            }        }    }   
TheadLocal不是很清楚的小伙伴可以移步到这,

ThreadLocal源码解析

http://blog.csdn.net/msn465780/article/details/78673656   点击打开链接

    /** For ThreadLocal, much faster to set (and get multiple values). */    final static class PostingThreadState {        final List eventQueue = new ArrayList<>();        boolean isPosting;        boolean isMainThread;        Subscription subscription;        Object event;        boolean canceled;    }   


PostingTheadState是一个静态类内部太监类,说白了就是一个实体,用来存储当前线程和post事件的一些状态。

一开始是存储post的事件,因为可能有很多地方都在post,接下来循环调用postSingleEvent(),

    private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {        Class<?> eventClass = event.getClass();        boolean subscriptionFound = false;        // eventInheritance默认为true        if (eventInheritance) {            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 {            subscriptionFound = postSingleEventForEventType(event, postingState, eventClass);        }        if (!subscriptionFound) {            if (logNoSubscriberMessages) {                // post事件,但是没有地方注册就打印出提示日志                logger.log(Level.FINE, "No subscribers registered for event " + eventClass);            }            if (sendNoSubscriberEvent && eventClass != NoSubscriberEvent.class &&                    eventClass != SubscriberExceptionEvent.class) {                // 不知道为啥还要执行以下代码,既然没有注册这个事件还去post一个未被注册的新事件,不是形成了递归吗?                post(new NoSubscriberEvent(this, event));            }        }    }


代码核心是调用postSingleEventForEventType()

    private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class<?> eventClass) {        CopyOnWriteArrayList subscriptions;        synchronized (this) {            // 从储存regist的方法中获取事件对应的方法            subscriptions = subscriptionsByEventType.get(eventClass);        }        if (subscriptions != null && !subscriptions.isEmpty()) {            // 开始循环把同一个事件post到注册者,意思就是调用这个事件订阅的方法            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;    }


哈哈,看到了吧,根据事件的Class对象subscriptionsByEventType.get(eventClass) 获取到相关的订阅者和方法,subscriptionsByEventType 还熟悉吗?就是register的时候用来保存的那个HashMap,那到这个方法后干啥呢?调用

postToSubscription(),这个方法还熟悉吗?前面粘性事件Sticky中提到过,就是用的它,是它是它就是它!

    private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {        switch (subscription.subscriberMethod.threadMode) {            case POSTING:                invokeSubscriber(subscription, event);                break;            case MAIN:                if (isMainThread) {                    // 如果post()在主线程,则立即反射调用订阅方法                    invokeSubscriber(subscription, event);                } else {                    // 否认,加入UI线程消息队列末尾                    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) {                    // 如果post()的线程为UI线程,则在线程池中反射调用订阅方法                    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);        }    }

switch语句根据订阅方法的时候,注解中指定线程,分别post事件,一个一个的讲下为啥这么区分,先看下都用到的方法invokeSubscriber(),

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


订阅方法的Method对象调用invoke(),是一种反射机制,参数中知道了订阅者对象,订阅者方法的事件参数对象,那么就可以直接调用到这个订阅方法了,也就达到发送事件接受到事件的循环了。


POSTING 

未指定订阅方法线程的时候默认值,直接调用,post在哪个线程,这个订阅方法就在哪个线程


MAIN           

指定订阅方法在UI线程中执行,如果当前为UI线程直接调用,否则利用MainThreadSupport对象加入UI线程消息队列                               末尾执行,MainThreadSupport其实就是主线程的Handler对象,后面再讲


MAIN_ORDERED   

这个和MAIN有啥区别呢?其实区别就是如果MainThreadSupport存在会优先加入UI线程消息队列末尾,否则才是立即执行


BACKGROUND

如果当前为主线程,加入后台线程执行,否则立即执行


ASYNC

不管当前什么线程,都在后台执行


post主干逻辑基本都说完了,再说下刚才那几个poster,MainThreadSupport、BackgroundPoster、AsyncPoster

他们都是接口,继承于Poster。


MainThreadSupport

public class HandlerPoster extends Handler implements Poster {    private final PendingPostQueue queue;    private final int maxMillisInsideHandleMessage;    private final EventBus eventBus;    private boolean handlerActive;    protected HandlerPoster(EventBus eventBus, Looper looper, int maxMillisInsideHandleMessage) {        super(looper);        this.eventBus = eventBus;        this.maxMillisInsideHandleMessage = maxMillisInsideHandleMessage;        // 创建一个自定义的队列        queue = new PendingPostQueue();    }    public void enqueue(Subscription subscription, Object event) {        // 获取存储pendingPost  list中最末一个        PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);        synchronized (this) {            // 获取到的pendingPost 入队            queue.enqueue(pendingPost);            // 当前handler对象是否还活动,如果没有活动就让它活动起来,这里的代码就相当于启动handler的作用            // 让handler处于发送、接受消息的循环中            if (!handlerActive) {                handlerActive = true;                // 发送空消息,在消息队列末尾,就会执行下面的handleMessage(),如果发送消息未成功,抛出异常                if (!sendMessage(obtainMessage())) {                    throw new EventBusException("Could not send handler message");                }            }        }    }    @Override    public void handleMessage(Message msg) {        boolean rescheduled = false;        try {            // 获取手机开机到现在的时间(毫秒),不包含睡眠时间            long started = SystemClock.uptimeMillis();            // 开启一个循环            while (true) {                // 获取队列头部的pendingPost                PendingPost pendingPost = queue.poll();                if (pendingPost == null) {                    synchronized (this) {                        // Check again, this time in synchronized                        // 继续获取剩下队列头部的pendingPost                        pendingPost = queue.poll();                        if (pendingPost == null) {                            // 如果获取了两次都是null,那么handlerActive = false;跳出方法                            handlerActive = false;                            return;                        }                    }                }                // 通过反射调用订阅者对象的订阅方法                eventBus.invokeSubscriber(pendingPost);                // 计算反射调用这个订阅方法的执行耗费时间(毫秒)                long timeInMethod = SystemClock.uptimeMillis() - started;                // 默认最大调用时间间隔是10毫秒,如果小于就继续循环从队列中取订阅方法反射调用,                // 如果大于就把剩下需要调用的加入消息队列末尾,然后又来执行handleMessage(),                // 因为这是在UI线程中进行的,如果调用时间过长,很容易出现ANR,所以把剩下没                // 调用完的加入消息队列末尾,让UI的其他操作先执行,防止阻塞                if (timeInMethod >= maxMillisInsideHandleMessage) {                    if (!sendMessage(obtainMessage())) {                        throw new EventBusException("Could not send handler message");                    }                    // 因为已经加入了队列末尾,所有这个方法没有作用了可以退出去了                    rescheduled = true;                    return;                }            }        } finally {            handlerActive = rescheduled;        }    }}

作用就是把post加入到UI线程消息队列末尾执行


BackgroundPoster

final class BackgroundPoster implements Runnable, Poster {    private final PendingPostQueue queue;    private final EventBus eventBus;    private volatile boolean executorRunning;    BackgroundPoster(EventBus eventBus) {        this.eventBus = eventBus;        queue = new PendingPostQueue();    }    public void enqueue(Subscription subscription, Object event) {        PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);        synchronized (this) {            queue.enqueue(pendingPost);            // 线程池是否活跃中,如果没有,则开启            if (!executorRunning) {                executorRunning = true;                // 把当前BackgroundPoster对象放入线程池中并执行                eventBus.getExecutorService().execute(this);            }        }    }    @Override    public void run() {        try {            try {                while (true) {                    // 从PendingPostQueue中取头部PendingPost,如果取两次都为null,退出方法                    PendingPost pendingPost = queue.poll(1000);                    if (pendingPost == null) {                        synchronized (this) {                            // Check again, this time in synchronized                            pendingPost = queue.poll();                            if (pendingPost == null) {                                executorRunning = false;                                return;                            }                        }                    }                    // 利用反射调用订阅方法                    eventBus.invokeSubscriber(pendingPost);                }            } catch (InterruptedException e) {                eventBus.getLogger().log(Level.WARNING, Thread.currentThread().getName() + " was interruppted", e);            }        } finally {            executorRunning = false;        }    }}


创建了一个线程池,然后在后台中执行


AsyncPoster

class AsyncPoster implements Runnable, Poster {    private final PendingPostQueue queue;    private final EventBus eventBus;    AsyncPoster(EventBus eventBus) {        this.eventBus = eventBus;        queue = new PendingPostQueue();    }    public void enqueue(Subscription subscription, Object event) {        PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);        queue.enqueue(pendingPost);        eventBus.getExecutorService().execute(this);    }    @Override    public void run() {        PendingPost pendingPost = queue.poll();        if(pendingPost == null) {            throw new IllegalStateException("No pending post available");        }        eventBus.invokeSubscriber(pendingPost);    }}

跟BackgroundPoster相似


接下来看下注销事件


我们安卓中一般都会在Activity或者Fragment注册事件,如果不注销肯定会发生内存泄漏,导致内存溢出,

unregister()


    /**     * 储存事件及对应方法;     * key是事件的Class对象,value是订阅者及订阅的方法集合     */    private final Map, CopyOnWriteArrayList> subscriptionsByEventType;    /**     * 储存订阅者及事件Class对象;     * 用于判断订阅者是否注册过     */    private final Map>> typesBySubscriber;

    /** Unregisters the given subscriber from all event classes. */    public synchronized void unregister(Object subscriber) {        List> 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());        }    }
    /** Only updates subscriptionsByEventType, not typesBySubscriber! Caller must update typesBySubscriber. */    private void unsubscribeByEventType(Object subscriber, Class<?> eventType) {        List 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--;                }            }        }    }

其实我都不用解析了,还记得开始我提到过EventBus有几个成员变量,都是容器类,typesBySubscriber用于判断是否注册过,

subscriptionsByEventType这个很多地方都出现过,保存事件及对应订阅方法的,注销其实就是把这个订阅者和相关方法移除掉,

哈哈,是不是想到判断当前是否注册过的那个方法了,看下源码

    public synchronized boolean isRegistered(Object subscriber) {        return typesBySubscriber.containsKey(subscriber);    }


明白了吧!


到这里EventBus这个优秀的框架主干都解析完了,我可能很多地方没描述清楚,不过小伙伴们懂逻辑原理就行了,细微的方法可以下面慢慢看下了。


EventBus说白了就是根据注解把相关的方法都保存在一个HashMap里面,key为事件Class对象,value为订阅者及相关订阅方法的集合,发送事件的时候就根据这个事件的Class对象从HashMap中拿出来一个一个循环的反射调用订阅者的订阅方法。


好了,又可以愉快玩耍了
































更多相关文章

  1. Android Studio 编译提示 aapt.exe finished with non-zero exit
  2. 高级UI-事件传递
  3. android中处理json最佳方法
  4. [置顶] 彻底解决Android 应用方法数不能超过65K的问题
  5. Android JNI编程内存问题定位方法

随机推荐

  1. Android SDK中 tools 目录下的工具介绍
  2. ubuntu下第一个Jni例子
  3. 在Android中如何使用全局变量--Applicati
  4. Android(安卓)Activity生命周期管理 .
  5. [Android] 设置控件是否可见
  6. android CTS测试全pass攻略
  7. Android的dumpsys命令
  8. Android中的Intent和Intent-filter总结
  9. Java for Android
  10. Android进程间通信(一):AIDL使用详解