Android EventBus3.0使用及源码解析

来源:互联网 发布:初音未来手办淘宝 编辑:程序博客网 时间:2024/04/29 06:18

本文已授权微信公众号《非著名程序员》原创首发,转载请务必注明出处。

叨了个叨

最近因为换工作的一些琐事搞的我一个头两个大,也没怎么去学新东西,实在是有些愧疚。新项目用到了EventBus3.0,原来只是听说EventBus的鼎鼎大名,一直没仔细研究过。趁着周末有些时间,研究下代码,也算没有虚度光阴。

EventBus GitHub : https://github.com/greenrobot/EventBus

EventBus3.0简介

EventBus是greenrobot出品的一个用于Android中事件发布/订阅的库。以前传递对象可能通过接口、广播、文件等等,尤其像同一个Activity两个Fragment之间采用接口传递对象,十分的麻烦,而且耦合度较高。使用EventBus之后,这些将不再是问题。盗用GiHub上EventBus的一张图。
eventbus
可以看到,发布者(Publisher)使用post()方法将Event发送到Event Bus,而后Event Bus自动将Event发送到多个订阅者(Subcriber)。这里需要注意两个地方:(1)一个发布者可以对应多个订阅者。(2)3.0以前订阅者的订阅方法为onEvent()onEventMainThread()onEventBackgroundThread()onEventAsync()。在Event Bus3.0之后统一采用注解@Subscribe的形式,具体实现方式见下文。

EventBus3.0的使用

新建两个Activity,花3s扫一下即可。代码如下:

public class MainActivity extends Activity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        // 注册EventBus        EventBus.getDefault().register(this);        startActivity(new Intent(this,SecondActivity.class));    }    @Override    protected void onDestroy() {        super.onDestroy();        // 反注册EventBus        EventBus.getDefault().unregister(this);    }    // 主线程调用    @Subscribe(threadMode = ThreadMode.MAIN)    public void eventBusMain(String str){        Log.i("TAG", "MAIN:"+str+" Thread="+Thread.currentThread().getId());    }    // 1.发布线程为主线程,新开线程调用    // 2.发布线程为子线程,发布线程调用    @Subscribe(threadMode = ThreadMode.BACKGROUND)    public void eventBusBg(String str){        Log.i("TAG", "BACKGROUND:"+str+" Thread="+Thread.currentThread().getId());    }    // 在发布线程调用,默认值    @Subscribe(threadMode = ThreadMode.POSTING)    public void eventBusPosting(String str){        Log.i("TAG", "POSTING:"+str+" Thread="+Thread.currentThread().getId());    }    // 每次都新开线程调用    @Subscribe(threadMode = ThreadMode.ASYNC)    public void eventBusAsync(String str){        Log.i("TAG", "ASYNC:"+str+" Thread="+Thread.currentThread().getId());    }}public class SecondActivity extends Activity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_second);        EventBus.getDefault().post("from second activity mainThread: info");        Log.i("TAG", "Post thread="+Thread.currentThread().getId());        new Thread(new Runnable() {            @Override            public void run() {                EventBus.getDefault().post("from second activity childThread: info");                Log.i("TAG", "Post thread="+Thread.currentThread().getId());            }        }).start();    }}

MainActivityonCreate()/onDestroy()中分别注册/反注册EventBus。然后写了四个测试ThreadMode的方法,调用时机注释的很清楚,就不赘述了。最后在SecondActivity的主线程和子线程中分别调用Post()方法,注意,这里Post()方法的参数为Object类型,这也就意味着我们传递任何对象都是可以的,例如JavaBeanList<E>等等都是可以的,这里为了方便演示直接传递了String。Log信息如下:
main

child
第一张图中发布者发送线程为主线程,即Post thread = 1,在订阅者收到消息时,ThreadMode = MainThreadMode = Posting的方法都在主线程调用,ASYNCBACKGROUND都新开了线程。图二对比注释同理。

除此之外,Subscribe注解还支持prioritysticky属性。priority设置接收者的优先级,默认值为0。优先级高的方法先被调用,在方法调用完成后可以调用EventBus.getDefault().cancelEventDelivery(event) ;终止优先级低的方法的调用。sticky为粘性事件,默认为关闭状态。能够收到订阅之前发送到的最后一条消息,并且发送的方法不再是post()而是postSticky()

EventBus3.0源码解析

EventBus是Very的好用。耦合度大大的降低,而且代码十分优雅。它是怎么就做到了这么优雅的呢?知其然,知其所以然。下面就开始一步步的分析。

注解标签Subscribe

对注解不了解的同学可以看下这篇博客。

@Documented@Retention(RetentionPolicy.RUNTIME)@Target({ElementType.METHOD})public @interface Subscribe {    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;}public enum ThreadMode {    POSTING,    MAIN,    BACKGROUND,    ASYNC}

注解Subscribe在运行时解析,且只能加在METHOD上。其中有三个方法,threadMode()返回类型ThreadMode为枚举类型,默认值为POSTINGsticky()默认返回false,priority()默认返回0。

1. Register流程

EventBus#getDefault()

public EventBus() {    this(DEFAULT_BUILDER);}public static EventBus getDefault() {    if (defaultInstance == null) {        synchronized (EventBus.class) {            if (defaultInstance == null) {                defaultInstance = new EventBus();            }        }    }    return defaultInstance;}

EventBus采用双重校验锁设计为一个单例模式,奇怪的在于虽然设计为单例模式,但是构造方法确实public类型,这不是坑爹嘛!难道greenrobot在设计EventBus获取实例方法的时候在打LOL,一不小心打错了?原来啊,EventBus默认支持一条事件总线,通常是通过getDefault()方法获取EventBus实例,但也能通过直接new EventBus这种最简单的方式获取多条事件总线,彼此之间完全分开。设计之思想不禁让人拍案叫绝。

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

首先得到订阅者的报名.类名,即哪个具体类注册。然后调用subscriberMethodFinder.findSubscriberMethods(subscriberClass),从方法名和返回值来看,findSubscriberMethods()的作用应该是遍历查找订阅者中所有的订阅方法。

SubscriberMethodFinder#findSubscriberMethods()

List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {    // 查找缓存    List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);    if (subscriberMethods != null) {        // 缓存中有则直接返回        return subscriberMethods;    }    // 默认false    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;    }}

注意subscriberMethods.isEmpty(),如果注册了EventBus,但却没有使用注解Subscribe是会出现EventBusException异常的。下面跟进findUsingInfo()方法。

SubscriberMethodFinder#findUsingInfo()

private List<SubscriberMethod> findUsingInfo(Class<?> subscriberClass) {    // 从FIND_STATE_POOL数组中查找FindState,命中返回,否则直接new    FindState findState = prepareFindState();    // 初始化FindState    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 {            findUsingReflectionInSingleClass(findState);        }        // 将findState.clazz变为改类的父类        findState.moveToSuperclass();    }    return getMethodsAndRelease(findState);}// SubscriberMethodFinder$FindState#initForSubscriber()void initForSubscriber(Class<?> subscriberClass) {    this.subscriberClass = clazz = subscriberClass;    skipSuperClasses = false;    subscriberInfo = null;}

findState.subscriberInfo默认null,那么就进入到findUsingReflectionInSingleClass(findState),先看下这个方法,等下还要返回来看。

SubscriberMethodFinder#findUsingReflectionInSingleClass()

private static final int MODIFIERS_IGNORE = Modifier.ABSTRACT | Modifier.STATIC | BRIDGE | SYNTHETIC;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修饰,而且不能为MODIFIERS_IGNORE        // MODIFIERS_IGNORE定义为ABSTRACT、STATIC、BRIDGE、SYNTHETIC。        if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) {            // 获取方法所有参数类型            Class<?>[] parameterTypes = method.getParameterTypes();            if (parameterTypes.length == 1) {                // 是否有Subscribe注解标签                Subscribe subscribeAnnotation = method.getAnnotation(Subscribe.class);                if (subscribeAnnotation != null) {                    // 带有Subscribe注解标签的方法的第一个参数类型                    Class<?> eventType = parameterTypes[0];                    // 关联method, eventType到anyMethodByEventType                    if (findState.checkAdd(method, eventType)) {                        ThreadMode threadMode = subscribeAnnotation.threadMode();                        // 构造SubscriberMethod,并且添加到findState.subscriberMethods                        findState.subscriberMethods.add(new SubscriberMethod(method, eventType, threadMode,                                subscribeAnnotation.priority(), subscribeAnnotation.sticky()));                    }                }            // strictMethodVerification 默认为false,不会抛出异常,但还是建议符合规范            } 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");        }    }}// `SubscriberMethodFinder#checkAdd()`boolean checkAdd(Method method, Class<?> eventType) {    // 2 level check: 1st level with event type only (fast), 2nd level with complete signature when required.    // Usually a subscriber doesn't have methods listening to the same event type.    Object existing = anyMethodByEventType.put(eventType, method);    if (existing == null) {        return true;    } else {         ...}

接下来返回SubscriberMethodFinder#findUsingInfo()接着看,在findUsingInfo()中循环执行完后return getMethodsAndRelease(findState)

static class FindState {    final List<SubscriberMethod> subscriberMethods = new ArrayList<>();    ...}private List<SubscriberMethod> getMethodsAndRelease(FindState findState) {    List<SubscriberMethod> 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;}

getMethodsAndRelease()中将findState置空,存放进FIND_STATE_POOL数组,最后返回findState.subscriberMethods。返回EventBus#register()

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

调用SubscriberMethodFinder#findSubscriberMethods()后,以List<SubscriberMethod>形式返回了订阅者所有的订阅事件。然后遍历执行subscribe()方法。看样子应该是遍历List<SubscriberMethod>,然后将订阅者和订阅事件绑定。没撒好说的,跟进subscribe()

EventBus#subscribe()

private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {    // 获取订阅事件的类型,即订阅方法中的唯一参数类型    Class<?> eventType = subscriberMethod.eventType;    // 用订阅者和订阅方法构造一个Subscription对象    Subscription newSubscription = new Subscription(subscriber, subscriberMethod);    // 查找所有的订阅了订阅事件的订阅者    CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType);    // 没有订阅者订阅过则新建个CopyOnWriteArrayList<subscriptions>,并put进subscriptionsByEventType PS:CopyOnWriteArrayList支持并发读写    if (subscriptions == null) {        subscriptions = new CopyOnWriteArrayList<>();        subscriptionsByEventType.put(eventType, subscriptions);    } else {        // 订阅者List不为空,而且已经包含了newSubscription,则会抛出异常。即:订阅者不能重复订阅同一事件        if (subscriptions.contains(newSubscription)) {            throw new EventBusException("Subscriber " + subscriber.getClass() + " already registered to event "                    + eventType);        }    }    int size = subscriptions.size();    // 根据订阅者优先级,增加到订阅者列表subscriptions的相应位置    for (int i = 0; i <= size; i++) {        if (i == size || subscriberMethod.priority > subscriptions.get(i).subscriberMethod.priority) {            subscriptions.add(i, newSubscription);            break;        }    }    // 获取订阅者所有订阅事件的列表,默认为null    List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);    if (subscribedEvents == null) {        subscribedEvents = new ArrayList<>();        typesBySubscriber.put(subscriber, subscribedEvents);    }    // 将订阅事件添加进对应订阅者的订阅列表    subscribedEvents.add(eventType);    // sticky默认为false    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);        }    }}

EventBus#Register()其实只做了三件事:

1. 查找订阅者所有的订阅事件

2. 将订阅事件作为key,所有订阅了此订阅事件的订阅者作为value存放进subscriptionsByEventType

3. 将订阅者作为key,订阅者的所有订阅事件作为value存放进typesBySubscriber

至此,EventBus.getDefault().register(this)流程完毕。

2. Post流程

EventBus#getDefault()

获取EventBus实例。和Register流程中一样,不再赘述。

EventBus#post()

/** Posts the given event to the event bus. */public void post(Object event) {    // 依据不同的线程获取相应的刚初始化的PostingThreadState    PostingThreadState postingState = currentPostingThreadState.get();    List<Object> eventQueue = postingState.eventQueue;    // 将event加入到postingState.eventQueue    eventQueue.add(event);    // isPosting默认false    if (!postingState.isPosting) {        // 判断是否是主线程        postingState.isMainThread = Looper.getMainLooper() == Looper.myLooper();        postingState.isPosting = true;        if (postingState.canceled) {            throw new EventBusException("Internal error. Abort state was not reset");        }        try {            // 遍历发送eventQueue中的event            while (!eventQueue.isEmpty()) {                postSingleEvent(eventQueue.remove(0), postingState);            }        } finally {            postingState.isPosting = false;            postingState.isMainThread = false;        }    }}

上面代码中currentPostingThreadStateThreadLocal<PostingThreadState>对象,对ThreadLocal<>机制不了解的同学,可以查看这篇博客。下面跟进postSingleEvent()方法。

EventBus#postSingleEvent()

private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {    // 获取event的类型    Class<?> eventClass = event.getClass();    boolean subscriptionFound = false;    // eventInheritance默认为true    if (eventInheritance) {        // 依据订阅事件类型,将订阅事件类型及所有父类添加进eventTypes。详情见下文EventBus.lookupAllEventTypes()分析        List<Class<?>> eventTypes = lookupAllEventTypes(eventClass);        int countTypes = eventTypes.size();        // 遍历countTypes,通过调用postSingleEventForEventType()方法通知所有订阅者        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) {            Log.d(TAG, "No subscribers registered for event " + eventClass);        }        if (sendNoSubscriberEvent && eventClass != NoSubscriberEvent.class &&                eventClass != SubscriberExceptionEvent.class) {            post(new NoSubscriberEvent(this, event));        }    }}

EventBus#lookupAllEventTypes()

private static List<Class<?>> lookupAllEventTypes(Class<?> eventClass) {    synchronized (eventTypesCache) {        // 根据订阅事件查找所有自身及父类,eventTypes默认为null        List<Class<?>> eventTypes = eventTypesCache.get(eventClass);        if (eventTypes == null) {            eventTypes = new ArrayList<>();            Class<?> clazz = eventClass;            while (clazz != null) {                // 将订阅事件添加进eventTypes                eventTypes.add(clazz);                // 遍历订阅事件的所有父类,依次添加进eventTypes                addInterfaces(eventTypes, clazz.getInterfaces());                clazz = clazz.getSuperclass();            }            // 将订阅事件和包含订阅事件自身及所有父类的eventTypes添加进eventTypesCache            eventTypesCache.put(eventClass, eventTypes);        }        return eventTypes;    }}

现在假设传递的数据为Person类,而Person类实现了IPerson接口。通过上面的分析可以得出结论:在传递对象(Person)的时候,订阅事件中参数为被传递对象的所有父类订阅事件(IPerson)也都会被调用。笔者已经验证通过,感兴趣的同学可以再验证一下。

EventBus#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 {                // 参数解释:subscription-被遍历到的订阅者;event-订阅事件参数(子类);                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;}

EventBus#register()最后总结道:将订阅事件作为key,所有订阅了此订阅事件的订阅者作为value存放进subscriptionsByEventType。这里就依据订阅事件然后查找对应所有的订阅者。注意:由于遍历订阅事件参数所有父类的原因,一个订阅事件的Post第一次执行postToSubscription()时,subscription参数,遍历时为订阅事件的订阅者。之后再调用postToSubscription()时,subscription参数都为订阅时间父类的订阅者。而event参数则一直是订阅事件中的唯一参数(最底层子类)。

EventBus#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 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确定分发类型。这里以最常用的Main为例,其余两个Poster同理。如果是isMainThread=true,那么直接调用invokeSubscriber(),否则调用mainThreadPoster.enqueue()。下面分别解释这两种情况。

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

没撒好说的,直接反射调用订阅者的订阅事件。注意:参数event是子类对象,就算调用订阅事件中唯一参数是参数的父类,那么传递的仍然是子类对象。笔者已经验证,感兴趣的同学可以自行验证。然后查看HandlerPoster#enqueue()

HandlerPoster#enqueue()

final class HandlerPoster extends Handler {    ...    void enqueue(Subscription subscription, Object event) {        // 尝试从pendingPostPool中获取pendingPost,没有则直接new PendingPost        PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);        synchronized (this) {            // 加入队列            queue.enqueue(pendingPost);            if (!handlerActive) {                handlerActive = true;                // 发送空消息 调用handleMessage                if (!sendMessage(obtainMessage())) {                    throw new EventBusException("Could not send handler message");                }            }        }    }    @Override    public void handleMessage(Message msg) {        // 已经切换到主线程         while (true) {            // 遍历获取queue中的PendingPost对象           PendingPost pendingPost = queue.poll();            ...            // 调用eventBus.invokeSubscriber            eventBus.invokeSubscriber(pendingPost);            ...        }    }}

EventBus#invokeSubscriber()

void invokeSubscriber(PendingPost pendingPost) {    // 提取订阅事件    Object event = pendingPost.event;    // 提取订阅者    Subscription subscription = pendingPost.subscription;    // 释放pendingPost    PendingPost.releasePendingPost(pendingPost);    if (subscription.active) {        // 反射调用订阅者的订阅事件        invokeSubscriber(subscription, event);    }}

至此,订阅者在相应线程调用订阅事件完成,EventBus.getDefault().Post()流程完毕。

EventBus#Post()也只做了三件事

1. 根据订阅事件在subscriptionsByEventType中查找相应的订阅者

2. 分发订阅者的订阅事件调用线程

2. 通过反射调用订阅者的订阅事件

3. unregister流程

EventBus#getDefault()

获取EventBus实例。和Register流程中一样,不再赘述。

EventBus#unregister()

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 {        Log.w(TAG, "Subscriber to unregister was not registered before: " + subscriber.getClass());    }}

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

EventBus#register()最后总结道:

将订阅事件作为key,所有订阅了此订阅事件的订阅者作为value存放进subscriptionsByEventType

将订阅者作为key,订阅者的所有订阅事件作为value存放进typesBySubscriber

现在要反注册咯。移除相应的keyvalue即可。EventBus3.0的使用及源码解析到此结束,Have a nice day~

7 0
原创粉丝点击