Android框架学习—EventBus源码分析

参考文章:
https://blog.csdn.net/u011240877/article/details/73196808

https://blog.csdn.net/sted_zxz/article/details/79949465在这里插入图片描述

EventBus是一个事件发布/订阅轻量级框架,能够简化组件间的通信,有效地将事件发送者和订阅者解耦,能避免复杂的依赖性和生命周期问题。EventBus可以代替Android传统的Intent,Handler,Broadcast或接口函数,在Fragment,Activity,Service线程之间传递数据,执行方法。

1.基本概念

eventbus的使用非常便捷,一次事件的传递有三个参与者
(1)Event事件:被传递的对象,可以是自定义的任意类型。
(2)Subscriber事件订阅者:3.0之后事件处理的方法名可以随意取,不过需要加上注解@subscrib,并且制定线程模型,默认是POSTING(在Publisher所在的线程执行Subscriber的方法)
(3)Publisher事件发布者:可以在任意线程中发布事件,一般情况下,使用EventBus.getDefault()得到一个EventBus对象,然后再调用post(Object o)方法即可。

线程模型

EventBus3.0有四种线程模型:
(1)POSTING(默认):表示执行订阅者方法所在的线程与事件发布者在同一个线程。
(2)MAIN:表示订阅者方法在主线程执行,因此不能在订阅者方法中进行耗时操作。
(3)BACKGROUND:表示订阅者方法执行在后台线程执行,因此不能进行UI操作。如果发布者所在线程是主线程,那么订阅者方法将会开启一个新的后台线程,如果发布者所在线程并非主线程,那么订阅者方法也会在同一个后台线程中执行。
(4)ASYNC:表示订阅者始终会新建一个不同于主线程和发布者所在线程的线程执行订阅者方法。

2.源码解析

获取EventBus对象

通过getDefault()方法获取实例:

    /** 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;
    }

然而EventBus的构造方法并非私有,一般情况下默认调用getDefault来获得EventBus对象,然而也可以创建多个EventBus实例,这些对象之间相互独立,会发布和订阅各自的事件。

getDefault() 使用默认的 EventBusBuilder 构建了一个 EventBus,从上面的代码我们可以看到,EventBus 类中包含的关键属性如下:

eventTypesCache :保存事件类型的缓存,HashMap

subscriptionsByEventType:事件类型与订阅者列表的映射,HashMap

typesBySubscriber:订阅的类与订阅的事件关联列表,HashMap
stickyEvents:粘性事件,ConcurrentHashMap
currentPostingThreadState:当前发送线程的状态,ThreadLocal
mainThreadPoster:主线程的消息发送者,Handler
backgroundPoster:子线程的消息发送者,Runnable
asyncPoster:异步消息发送者,Runnable
subscriberMethodFinder:订阅方法查找
executorService:线程池

    public EventBus() {
        this(DEFAULT_BUILDER);
    }
    
    EventBus(EventBusBuilder builder) {
        logger = builder.getLogger();
        subscriptionsByEventType = new HashMap<>();
        typesBySubscriber = new HashMap<>();
        stickyEvents = new ConcurrentHashMap<>();
        mainThreadSupport = builder.getMainThreadSupport();
        mainThreadPoster = mainThreadSupport != null ? mainThreadSupport.createPoster(this) : null;
        backgroundPoster = new BackgroundPoster(this);
        asyncPoster = new AsyncPoster(this);
        indexCount = builder.subscriberInfoIndexes != null ? builder.subscriberInfoIndexes.size() : 0;
        subscriberMethodFinder = new SubscriberMethodFinder(builder.subscriberInfoIndexes,builder.strictMethodVerification, builder.ignoreGeneratedIndex);
        logSubscriberExceptions = builder.logSubscriberExceptions;
        logNoSubscriberMessages = builder.logNoSubscriberMessages;
        sendSubscriberExceptionEvent = builder.sendSubscriberExceptionEvent;
        sendNoSubscriberEvent = builder.sendNoSubscriberEvent;
        throwSubscriberException = builder.throwSubscriberException;
        eventInheritance = builder.eventInheritance;
        executorService = builder.executorService;
    }

注册订阅者

    /**
     * Registers the given subscriber to receive events. Subscribers must call {@link #unregister(Object)} once they
     * are no longer interested in receiving events.
     * <p/>
     * 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<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
        synchronized (this) {
            for (SubscriberMethod subscriberMethod : subscriberMethods) {
                subscribe(subscriber, subscriberMethod);
            }
        }
    }

在需要注册订阅者的类中调用register方法,可以看到register方法中首先会获得当前注册者的class对象,然后调用subscriberMethodFinder的方法查找该class对象中订阅者方法。

下面来看findSubscriberMethods方法的源码,该方法主要是获取class对象的订阅者方法列表,流程如下:
(1)首先通过METHOD_CACHE这个map中查找当前class对象是否已经有subscriberMethod的集合,如果有则直接返回map中缓存的集合。
(2)接着判断是否忽略EventBus注解器在编译期间生成的映射表,如果没忽略则通过映射表来查找subscriberMethod的集合,否则通过反射的方式查找。
(3)得到集合后,如果发现该类中没有任何用@Subscribe注解的方法,则会抛出异常,如果有则将得到的集合加入缓存。

    List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
        //尝试从缓存中获取SubscriberMethod的集合
        List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);
        if (subscriberMethods != null) {
            return subscriberMethods;
        }
         //是否忽略编译时注解器生成的映射表
        if (ignoreGeneratedIndex) {
            //如果忽略,则通过反射查找当前类中的subscriberMethod
            subscriberMethods = findUsingReflection(subscriberClass);
        } else {
            //反之,则通过注解器生成的映射表查找
            subscriberMethods = findUsingInfo(subscriberClass);
        }
        if (subscriberMethods.isEmpty()) {
            //如果注册了,当时当前类中没有找到任何@Subscribe注解的方法则会抛出异常
            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;
        }
    }

由于默认不会忽略映射表,主要就看findUsingInfo的方法。

 private List<SubscriberMethod> findUsingInfo(Class<?> subscriberClass) {
    //初始化findState对象,通过维护一个数组构成的对象池缓存了findState对象,以防止频繁创建
    FindState findState = prepareFindState();
    findState.initForSubscriber(subscriberClass);
    while (findState.clazz != null) {
        //尝试从注解器在编译时生成的映射表中获取订阅信息
        findState.subscriberInfo = getSubscriberInfo(findState);
        if (findState.subscriberInfo != null) {
            SubscriberMethod[] array = findState.subscriberInfo.getSubscriberMethods();
            //如果在映射表中找到了订阅信息,通过遍历的方式将订阅者方法存入findState对象中
            for (SubscriberMethod subscriberMethod : array) {··
                if (findState.checkAdd(subscriberMethod.method, subscriberMethod.eventType)) {
                    findState.subscriberMethods.add(subscriberMethod);
                }
            }
        } else {
             //getSubscriberInfo返回值为null,表示映射表不存在,则通过反射的方式构造findState对象
            findUsingReflectionInSingleClass(findState);
        }
  //在父类中查找订阅者方法
        findState.moveToSuperclass();
    }
    //返回订阅者方法的集合并且释放findState对象
    return getMethodsAndRelease(findState);
}

private SubscriberInfo getSubscriberInfo(FindState findState) {
    if (findState.subscriberInfo != null && findState.subscriberInfo.getSuperSubscriberInfo() != null) {
        SubscriberInfo superclassInfo = findState.subscriberInfo.getSuperSubscriberInfo();
        if (findState.clazz == superclassInfo.getSubscriberClass()) {
            return superclassInfo;
        }
    }
    if (subscriberInfoIndexes != null) {
        for (SubscriberInfoIndex index : subscriberInfoIndexes) {
            SubscriberInfo info = index.getSubscriberInfo(findState.clazz);
            if (info != null) {
                return info;
            }
        }
    }
    return null;
}

最后得到订阅者方法集合后,会将当前类的class对象和订阅者方法集合存到METHOD_CACHE这个map中。

回到register方法,获取当前类的订阅者方法集合后,会通过subscribe方法绑定当前对象和集合中的方法。

public void register(Object subscriber) {
    Class<?> subscriberClass = subscriber.getClass();
    List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
    synchronized (this) {
        for (SubscriberMethod subscriberMethod : subscriberMethods) {
            subscribe(subscriber, subscriberMethod);
        }
    }
}

subscribe方法源码:

 // Must be called in synchronized block
    private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
        //获取订阅者方法的事件类型
        Class<?> eventType = subscriberMethod.eventType;
        //创建一个subscription保存订阅者和订阅者方法
        Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
        //获取当前订阅事件的集合
        CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
        //如果没有当前订阅者事件没有对应的subscription集合,则新建一个集合,并将当前订阅者和订阅者方法的subscription对象 和 订阅者事件 存入   	       //subscriptionsByEventType这个map中
        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);
            }
        }
         //根据优先级将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是订阅者的类和该类的订阅者事件的map,这段是尝试创建订阅事件类型和所属类的映射
        List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);
        if (subscribedEvents == null) {
            subscribedEvents = new ArrayList<>();
            typesBySubscriber.put(subscriber, subscribedEvents);
        }
        subscribedEvents.add(eventType);
    
         //处理黏性事件。如果是黏性事件,立即发送出去
        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);
            }
        }
    
    }

在这里插入图片描述

发布事件

Post方法主要流程:
1)获取当前线程的发送状态
2)将当前事件添加进队列中
3)将队列中的事件依次发送

   /** Posts the given event to the event bus. */
    public void post(Object event) {
        //获取当前线程的发送状态
        PostingThreadState postingState = currentPostingThreadState.get();
        List<Object> eventQueue = postingState.eventQueue;
        //将当前事件加入发送队列
        eventQueue.add(event);
         
         //如果没有其他事件正在被发送
        if (!postingState.isPosting) {
            //准备发送当前事件,修改postingState状态
            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的状态
                postingState.isPosting = false;
                postingState.isMainThread = false;
            }
        }
    }

其中currentPostingThreadState保存了每个线程的相关状态,是一个TheardLocal,他保存了当前线程的事件队列,发送状态,是否为主线程等状态值,只要当前线程不处于遍历发送的状态,将当前事件添加进队列后就会开始发送。

    private final ThreadLocal<PostingThreadState> currentPostingThreadState = new ThreadLocal<PostingThreadState>() {
        @Override
        protected PostingThreadState initialValue() {
            return new PostingThreadState();
        }
    };
    
    /** For ThreadLocal, much faster to set (and get multiple values). */
    final static class PostingThreadState {
        //当前线程的事件队列
        final List<Object> eventQueue = new ArrayList<>();
        //是否正在发送
        boolean isPosting;
        //是否为主线程
        boolean isMainThread;
        Subscription subscription;
        Object event;
        boolean canceled;
    }

回到Post方法,发送事件最后都要通过postSingleEvent方法,首先找到当前事件的所有父类和接口然后通过postSingleEventForEventType方法发送事件。

    private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {
        //获取事件的class对象
        Class<?> eventClass = event.getClass();
        boolean subscriptionFound = false;
        if (eventInheritance) {
            //找到这个事件的所有父类和接口
            List<Class<?>> 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) {
                logger.log(Level.FINE, "No subscribers registered for event " + eventClass);
            }
            if (sendNoSubscriberEvent && eventClass != NoSubscriberEvent.class &&
                    eventClass != SubscriberExceptionEvent.class) {
                post(new NoSubscriberEvent(this, event));
            }
        }
    }

postSingleEventForEventType方法通过eventType在subscriptionsByEventType这个Map中拿到对应的Subscription集合,然后调用postToSubscription遍历集合依次将事件发送给订阅者。

    private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class<?> eventClass) {
        CopyOnWriteArrayList<Subscription> subscriptions;
        synchronized (this) {
            //找到当前事件对应的subscription集合
    //由于数据可能同时添加和操作,所以synchronized加锁并且使用CopyOnWriteArrayList
            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进行不同的操作。

    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 {
                    //如果当前不是主线程,入队,handler发送消息到主线程,在主线程中反射调用
                    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) {
                    //如果Poster处于主线程,将订阅者放到子线程线程池中执行
                    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,有一个反射调用方法和3种不同的Poster。

反射调用方法为 invokeSubscriber,代码很简单,就是直接使用反射调用订阅者的方法,如果订阅者方法要求被调用的线程和发送者在同一线程,就会直接调用invokeSubscriber来通过反射执行订阅者方法。否则就会交给三种发送者:
1)private final Poster mainThreadPoster;
2)private final BackgroundPoster backgroundPoster;
3)private final AsyncPoster asyncPoster;

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

HandlerPoster 主线程的事件发送者

final class HandlerPoster extends Handler {

    private final PendingPostQueue queue;
    private final int maxMillisInsideHandleMessage;
    private final EventBus eventBus;
    private boolean handlerActive;

    //...
}

HandlerPoster中持有一个PendingPostQueue对象,他是一个PendingPost的双向链表,具体内容如下:

    /**
     * 待发送消息的双向链表,生产者-消费者模型, 出队 wait - 入队 nofityAll
     */
    final class PendingPostQueue {
        private PendingPost head;
        private PendingPost tail;
    
        synchronized void enqueue(PendingPost pendingPost) {
            if (pendingPost == null) {
                throw new NullPointerException("null cannot be enqueued");
            }
            if (tail != null) {
                tail.next = pendingPost;
                tail = pendingPost;
            } else if (head == null) {
                head = tail = pendingPost;
            } else {
                throw new IllegalStateException("Head present, but no tail");
            }
            notifyAll();
        }
    
        synchronized PendingPost poll() {
            PendingPost pendingPost = head;
            if (head != null) {
                head = head.next;
                if (head == null) {
                    tail = null;
                }
            }
            return pendingPost;
        }
    
        synchronized PendingPost poll(int maxMillisToWait) throws InterruptedException {
            if (head == null) {
                wait(maxMillisToWait);
            }
            return poll();
        }
    
    }

PendingPost是对发送事件和订阅者的又一次封装,和之前查找订阅者方法的FindState一样,都是为了避免在多个方法传递参数时参数太多,另外还采用了对象复用池,对象使用后不销毁,而是加入复用池中,就不用重复创建非常多的对象。

    /**
     * 等待发送的事件队列,就是一个对象复用池
     */
    final class PendingPost {
        private final static List<PendingPost> pendingPostPool = new ArrayList<PendingPost>();  //对象复用池
    
        Object event;
        Subscription subscription;
        PendingPost next;
    }

HandlerPoster的关键代码:

    public void enqueue(Subscription subscription, Object event) {
        PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
        synchronized (this) {
            queue.enqueue(pendingPost);
            if (!handlerActive) {
                handlerActive = true;
                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 = queue.poll();
                if (pendingPost == null) {
                    synchronized (this) {
                        // Check again, this time in synchronized
                        pendingPost = queue.poll();
                        if (pendingPost == null) {
                            handlerActive = false;
                            return;
                        }
                    }
                }
                eventBus.invokeSubscriber(pendingPost);
                long timeInMethod = SystemClock.uptimeMillis() - started;
                if (timeInMethod >= maxMillisInsideHandleMessage) {
                    if (!sendMessage(obtainMessage())) {
                        throw new EventBusException("Could not send handler message");
                    }
                    rescheduled = true;
                    return;
                }
            }
        } finally {
            handlerActive = rescheduled;
        }
    }

由于mainThreadPoster初始化时使用的是主线程的Looper所以handlerMessage会在主线程执行,不停的从队列中取出PendingPost,然后调用invokeSubscriber,可以看到 最终还是调用了反射调用方法。

BackgroundPoster 单一子线程发送者

    final class BackgroundPoster implements Runnable {
    
        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;
                    eventBus.getExecutorService().execute(this);    //使用线程池执行
                }
            }
        }
        //...
    
    }

可以看到,BackgroundPoster是一个Runnable的子类,在入队事件后,调用eventBus.getExectorService().execute(this)分配一个线程执行自己,触发调用run()方法。BackgroundPoster.run()类似HandlerPoster.handleMessage(),不停从队列中取出PendingPost,然后调用eventBus.invokeSubscriber(),最终还是通过反射调用订阅方法。由于BackgroundPoster是在一个线程中不停地反射调用订阅方法,如果某个订阅方法太耗时,会影响其他订阅方法的调用。

    {
        //...
        @Override
        public void run() {
            try {
                try {
                    while (true) {
                        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) {
                    Log.w("Event", Thread.currentThread().getName() + " was interruppted", e);
                }
            } finally {
                executorRunning = false;
            }
        }

AsyncPoster 异步发送者

AsyncPoster的代码很简单,可以看到AsyncPoster和BackgroundPoster一样都是Runnable的子类,都通过EventBus的线程池分配一个线程执行。不同的是BackgroundPoster在run()方法中串行调用队列中所有的订阅者方法,为了保证调用过程中另外入队情况的同步性,入队方法和run()方法都加了锁做同步处理

而AsyncPoster由于只执行一个订阅方法的调用(async线程模式下的总是会新建一个线程),有一个新的订阅方法就新建一个AsyncPoster.run()。因此必须控制ThreadMode为ASYNC的订阅方法,避免创建大量线程。

    class AsyncPoster implements Runnable {
    
        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);
        }
        //...
    }

发送流程

在这里插入图片描述

取消注册

可以看到 取消注册的方法很简单,主要是通过当前的订阅者subscriber获得所有的eventType构成的集合,遍历eventType集合,对每个eventType对应的Subscriptions集合中移除由当前订阅者构建的subscription对象。

    /** Unregisters the given subscriber from all event classes. */
    public synchronized void unregister(Object subscriber) {
        //获得这个订阅者类中的EventType集合
        List<Class<?>> subscribedTypes = typesBySubscriber.get(subscriber);
        if (subscribedTypes != null) {
            //遍历EventType集合,对每一个当前订阅者的EventType对应的Subscribition集合遍历,移除当前subscription的实例
            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<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
        if (subscriptions != null) {
            int size = subscriptions.size();
            //遍历eventType对应的subscription集合,移除当前subscriber对应的subscription
            for (int i = 0; i < size; i++) {
                Subscription subscription = subscriptions.get(i);
                if (subscription.subscriber == subscriber) {
                    subscription.active = false;
                    subscriptions.remove(i);
                    i--;
                    size--;
                }
            }
        }
    }

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值