zoukankan      html  css  js  c++  java
  • EventBus原理以及源代码分析

    一、概述

      EventBus是一个基于观察者模式的发布/订阅事件总线框架。将事件的发送者和接收者分开,其可以简化组件之间的通讯,相对于BroadcastReceiver其更轻量级也更易用。

    二、用法介绍

      EventBus的用法非常的简单,大致上就四步:

      1.注册事件

     @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            /**
             * 注册观察者对象
             */
            EventBus.getDefault().register(this);
        }

      2.消费事件

     /**
         * 用于接收post发送过来的事件
         * @param event 具体的事件主体
         */
        @Subscribe
        public void onMessageEvent(MessageEvent event) {
            switch (event.getArg1()) {
                case 0:
                    break;
                case 1:
                    break;
    
            }
        }

      3.取消事件

     @Override
        protected void onDestroy() {
            super.onDestroy();
            /**
             * 取消订阅
             */
            EventBus.getDefault().unregister(this);
        }

      4.发送事件

        /**
         * 发送消息
         */
        public void toPost() {
            MessageEvent event = new MessageEvent();
            event.setArg1(0);
            event.setObj(new Object());
            event.setMsg("我发送消息了");
            EventBus.getDefault().post(event);
        }
    

      

    三、具体的源代码分析

      1.我们从使用开始入手,先看下EventBus.getDefault()都干了写什么事情。

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

      从上面的代码我们可以看出EventBus是一个单例类而且是懒汉式的单例,为了保证整个应用中只有一个EventBus实例。

      在其构造方法中会进行一些初始化的工作,如:

    public EventBus() {
            this(DEFAULT_BUILDER);
        }
    
        EventBus(EventBusBuilder builder) {
            logger = builder.getLogger();
            //通过订阅事件类型查找订阅对象的map集合
            subscriptionsByEventType = new HashMap<>();
            typesBySubscriber = new HashMap<>();
            //粘性事件
            stickyEvents = new ConcurrentHashMap<>();
            //主线程支持
            mainThreadSupport = builder.getMainThreadSupport();
            //handler对象
            mainThreadPoster = mainThreadSupport != null ? mainThreadSupport.createPoster(this) : null;
            //runable对象
            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;
            //默认线程,CachedThreadPool
            executorService = builder.executorService;
        }
    

      1.subscriptionsByEventType通过event.getClass类型查找HashMap中的subscription集合。而subscription中存放的是subscriberMethod对象,subscriberMethod对象中又存放的是订阅者中用subscriber注解标注的Method、时间类型event.getClass、是否是粘性事件、线程模型、时间执行的优先级等信息。

      2.mainThreadPoster,其实它是HandlerPoster继承了handler并实现了poster,可以把其理解成主线程handler。调用其enqueue方法传入subscription和subscriber。并在其handleMessage方法中通过eventbus.invokeSubscriber(pendingPost) 放订阅方法在主线程中执行

      3.BackgroundPoster实现了runnable和poster对象,通过enqueue方法把subscription和subscriber传入,在run方法中执行eventbus.invokeSubscriber(pendingPost)

      4.AsyncPoster实现了Runnable和Poster接口,也是调用enqueue将Subscription和subscriber传入,并将AsyncPoster对象运行在线程池中,并执行run方法的中的eventBus.invokeSubscriber(pendingPost)

      5.executorService线程池,其具体实现是CachedThreadPool  

      以上的几步在后面的分析中会回使用到。

      2.EventBus.getDefault().register(this)方法

        /**
         * 注册订阅者对象
         * @param subscriber 订阅者
         */
        public void register(Object subscriber) {
            //获取订阅者的class对象
            Class<?> subscriberClass = subscriber.getClass();
            //根据订阅者class对象或者订阅者subscribe标注的方法集合SubscriberMethod
            List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
            synchronized (this) {//加锁,一次只能进一个线程
                for (SubscriberMethod subscriberMethod : subscriberMethods) {
                    //开始订阅,循环向subscriptionsByEventType中添加订阅对象。具体的做法是,根据事件类型取出订阅集合,然后向订阅集合中不断的加入
                    //订阅,并最终存入subscriptionsByEventType中
                    subscribe(subscriber, subscriberMethod);
                }
            }
        }
    

      在register方法内部,会获取到订阅者subscriber(activity)的class对象。并通过这个class对象获取到该订阅者中用subscriber标记的方法集合。通过SubscriberMethodFinder.findSubscriberMethods(subscriberClass)获取。

      在findSubscriberMethods内部首先会从缓存中获取,如果缓存中又就直接返回,如果缓存中没有就解析subscriberClass对象,并拿到subscriberClass对象中用subscriber注解标注过的方法、方法参数类型、线程模型、事件执行优先级、是否是粘性事件,并将以上信息封装到SubscriberMethod对象中。然后把SubscriberMethod对象加入集合返回。

    List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
            //先从缓存中获取,如果获取到了就直接返回。如果缓存中没有就查找带有subscribe标记的方法,并放到集合中
            //因为一个class对象中用subscribe标注的方法可能不止一个,所以要用集合把所有的都存入进去
            List<SubscriberMethod> 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;
            }
        }
    

      

    private List<SubscriberMethod> findUsingReflection(Class<?> subscriberClass) {
            FindState findState = prepareFindState();
            findState.initForSubscriber(subscriberClass);
            while (findState.clazz != null) {//如果订阅者对象不为空,执行下面这个while
                findUsingReflectionInSingleClass(findState);
                //去找父类
                findState.moveToSuperclass();
            }
            return getMethodsAndRelease(findState);
        }
    
        private void findUsingReflectionInSingleClass(FindState findState) {
            Method[] methods;
            try {
                //利用反射获取subscriber的方法集合
                methods = findState.clazz.getDeclaredMethods();
            } catch (Throwable th) {
                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);
                        if (subscribeAnnotation != null) {
                            //获取事件类型,由于只有一个参数所以parameterTypes取第一个就行了
                            Class<?> eventType = parameterTypes[0];
                            if (findState.checkAdd(method, eventType)) {
                                //获取线程模型,这个模型用于标注,用户自定义的事件是在主线程中执行还是在子线程中执行
                                ThreadMode threadMode = subscribeAnnotation.threadMode();
                                //把订阅者的方法存入subscriberMethod,并把SubscriberMethod存入方法集合中
                                findState.subscriberMethods.add(new SubscriberMethod(method, eventType, threadMode,
                                        subscribeAnnotation.priority(), subscribeAnnotation.sticky()));
                            }
                        }
                 ....省略了一些代码
            }
        }
    

      然后回过头来看EventBus的findSubscriberMethods方法中的subscriber方法,这个方法是执行订阅操作的。

      synchronized (this) {//加锁,一次只能进一个线程
                for (SubscriberMethod subscriberMethod : subscriberMethods) {
                    //开始订阅,循环向subscriptionsByEventType中添加订阅对象。具体的做法是,根据事件类型取出订阅集合,然后向订阅集合中不断的加入
                    //订阅,并最终存入subscriptionsByEventType中
                    subscribe(subscriber, subscriberMethod);
                }
            }
    

      循环遍历subscriberMethods集合,并把subscriber和SubscriberMethod封装成Subscription。并把Subscription添加到subscriptions集合。并以eventType为key,subscriptions为value将其缓存到名字为subscriptionsByEventType的HashMap中。

     private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
            //从subscriberMethod获取事件类型
            Class<?> eventType = subscriberMethod.eventType;
            //将订阅者对象和订阅方法存入Subscription中
            Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
            //先从缓存中取出订阅集合(根据事件类型),如果没有就创建一个
            CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
            if (subscriptions == null) {
                subscriptions = new CopyOnWriteArrayList<>();
                subscriptionsByEventType.put(eventType, subscriptions);
            } else {
                if (subscriptions.contains(newSubscription)) {
                    throw new EventBusException("Subscriber " + subscriber.getClass() + " already registered to event "
                            + eventType);
                }
            }
    
            int size = subscriptions.size();
            for (int i = 0; i <= size; i++) {
                if (i == size || subscriberMethod.priority > subscriptions.get(i).subscriberMethod.priority) {
                    //向订阅集合中加入订阅
                    subscriptions.add(i, newSubscription);
                    break;
                }
            }
    
            List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);
            if (subscribedEvents == null) {
                subscribedEvents = new ArrayList<>();
                typesBySubscriber.put(subscriber, subscribedEvents);
            }
            subscribedEvents.add(eventType);
    
            ...省略了一些代码
        }
    

      到此订阅结束。

      总结:

      1.在EventBus中对各个属性进行初始化、如:HashMap、线程池等

      2.获取subscriber的class对象,并通过SubscriberMethodFinder.findSubscriberMethods(subscriberClass)获取到subscriberClass中用subscriber注解标注的方法属性集合(方法、参数类型、线程模型、是否是粘性事件、事件优先级等)。这里面有一个判断条件,先检查缓存中是否有这些方法集合,如果有就直接返回,如果没有就编辑subscriberClass的方法集合选出用subscriber直接标注的方法,并取出方法、参数类型、线程模型、是否是粘性事件、事件优先级等信息,并将其封装为SubscriberMethod对象,然后将SubscriberMethod对象放入List集合返回。

      3.对subscriberMethods结合进行遍历,通过subscribe方法进行订阅。在subscribe方法内部会创建一个Subscription对象,并将subscriber对象和SubscriberMethod方法存入。并将Subscription对象加入到CopyOnWriteArrayList集合subscriptions。并以SubscriberMethod.eventType为key,subscriptions为value将数据存入subscriptionsByEventType的HashMap中。到此订阅就结束了。

      2.EventBus.getDefault().post(event)使用post方法发送订阅通知

      

    public void post(Object event) {
            //从ThreadLocal中取出当前线程中的状态数据
            PostingThreadState postingState = currentPostingThreadState.get();
            //从当前线程中取出事件队列(其实不是队列,就是一个list集合)
            List<Object> eventQueue = postingState.eventQueue;
            //向当前线程的事件队列中加入事件
            eventQueue.add(event);
    
            if (!postingState.isPosting) {
                //判断当前线程是不是主线程
                postingState.isMainThread = isMainThread();
                postingState.isPosting = true;
                if (postingState.canceled) {
                    throw new EventBusException("Internal error. Abort state was not reset");
                }
                try {
                    while (!eventQueue.isEmpty()) {//如果事件不为空,则对事件进行分发
                        postSingleEvent(eventQueue.remove(0), postingState);
                    }
                } finally {
                    postingState.isPosting = false;
                    postingState.isMainThread = false;
                }
            }
        }
    

      在post内部会创建一个PostingThreadState对象和一个消息队列eventQueue。其中PostingThreadState是一个ThreadLocal对象(其可以在不同的线程之间存储数据,且线程间的数据相互独立)

      并对postingState进行初始化,紧接着会调用postSingleEvent方法,并将事件和postingState传递进去。在postSingleEvent方法内部又会调用postSingleEventForEventType方法。

    private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class<?> eventClass) {
            CopyOnWriteArrayList<Subscription> subscriptions;//订阅集合
            synchronized (this) {
                //根据事件类型从订阅map中取出订阅集合
                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;
        }
    

      根据eventClass在subscriptionsByEventType的HashMap中取出Subscriptions集合,循环遍历subscriptions集合并通过postToSubscription方法对事件进行分发

     private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {
            switch (subscription.subscriberMethod.threadMode) {//从订阅对象中取出线程模型
                case POSTING://默认模式,在哪个线程中订阅就在哪个线程中执行
                    //具体的分发
                    invokeSubscriber(subscription, event);
                    break;
                case MAIN://如在主线程(UI线程)发送事件,则直接在主线程处理事件;如果在子线程发送事件,则先将事件入队列,然后通过 Handler 切换到主线程,依次处理事件。
                    if (isMainThread) {
                        invokeSubscriber(subscription, event);
                    } else {
                        mainThreadPoster.enqueue(subscription, event);
                    }
                    break;
                case MAIN_ORDERED://无论在那个线程发送事件,都先将事件入队列,然后通过 Handler 切换到主线程,依次处理事件
                    if (mainThreadPoster != null) {
                        mainThreadPoster.enqueue(subscription, event);
                    } else {
                        // temporary: technically not correct as poster not decoupled from subscriber
                        invokeSubscriber(subscription, event);
                    }
                    break;
                case BACKGROUND://如果在主线程发送事件,则先将事件入队列,然后通过线程池依次处理事件;如果在子线程发送事件,则直接在发送事件的线程处理事件
                    if (isMainThread) {
                        backgroundPoster.enqueue(subscription, event);
                    } else {
                        invokeSubscriber(subscription, event);
                    }
                    break;
                case ASYNC://无论在那个线程发送事件,都将事件入队列,然后通过线程池处理
                    asyncPoster.enqueue(subscription, event);
                    break;
                default:
                    throw new IllegalStateException("Unknown thread mode: " + subscription.subscriberMethod.threadMode);
            }
        }
    

      从上面的代码可以看出根据不同的线程模型会执行不同的方法内容。先看下invokeSubscriber(subscription,event)方法都干了啥

     /**
         * 具体执行订阅方法的类
         * @param subscription 订阅对象
         * @param event 事件
         */
        void invokeSubscriber(Subscription subscription, Object event) {
            try {
                //从订阅对象中取出SubscriberMehtod,然后调用其Method方法并执行方法的invoke来完成事件的执行
                subscription.subscriberMethod.method.invoke(subscription.subscriber, event);
            } catch (InvocationTargetException e) {
                handleSubscriberException(subscription, event, e.getCause());
            } catch (IllegalAccessException e) {
                throw new IllegalStateException("Unexpected exception", e);
            }
        }
    

      上面方法的执行非常的简单,其实就是从subscription中取出subscriberMethod对象,并取出subscriberMethod对象的method方法并执行method方法的invoke函数。执行完这一段之后在subscriber对象中用subscriber注解标注的方法就会执行了。也就是说到此处未知,从订阅到发送到接收就已经执行完了。

      上面说的是在那个线程中发送就在哪个线程中接收事件的线程模型。线面说下另外两个,无论如何在主线程中执行和无论如何在子线程中执行。主要看两个类HandlerPoster和BackgroundPoster这个两个为代表讲解一下。

      先看HandlerPoster

    public class HandlerPoster extends Handler implements Poster {
      .....省略了一些代码
        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) {
                   ...省略了一些代码
                    eventBus.invokeSubscriber(pendingPost);
                    ....省略了一些代码
    }
    

      如果再子线程发送事件,然后想让在在主线程中执行。那么首先就要调用HandlerPoster.enqueue方法,enqueue方法内部会调用sendMessage向主线程Handler发送消息,在Handler的handleMessage内部会接收消息通知,并执行eventBus.invokeSubscriber(pendingPost)。看到这一步其实就明了了,就是通过反射执行方法呗,不同的是执行过程已经切换到主线程了。

      再来看一下BackgroundPoster这个类。

    final class BackgroundPoster implements Runnable, Poster {
    
        ...省略了一些diamante
        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);
                }
            }
        }
    
        @Override
        public void run() {
            try {
                try {
                    while (true) {
                       ...省略了一些代码
                        eventBus.invokeSubscriber(pendingPost);
                    }
                } catch (InterruptedException e) {
                    eventBus.getLogger().log(Level.WARNING, Thread.currentThread().getName() + " was interruppted", e);
                }
            } finally {
                executorRunning = false;
            }
        }
    
    }
    

      从以上的源代码我们可以看出BackgroundPoster实现了Runnable和poster接口,并实现run方法和enqueue方法。在enqueue的内部会调用eventbus的线程池的execute(this)方法运行BackgroundPoster对象的run方法,在run方法内部会调用eventBus.invokeSubscriber(pendingPost)方法,这个方法目的非常明确,通过反射执行subscriber对象中用subscriber注解标注的方法。

      总结:

      1.在post方法内部对postingThreadState进行初始化并赋值

      2.调用postSingleEvent方法,在postSingleEvent方法内部调用postSingleEventForEventType方法,在postSingleEventForEventType方法内部根据eventType从subscriptionsByEventType中取出Subscriptions集合。循环遍历Subscriptions集合,并执行postToSubscription方法。在postToSubscription方法内部会根据不同的现场模型执行对应的方法。如:1.直接执行invokeSubscriber(subscription,eventObj) ,2.通过HandlerPoster.enqueue将执行事件切换到主线程中执行,最终也是会执行invokeSubscriber(pendingPost)方法,3.通过BackgroundPoster.enqueue方法将时间切换到子线程或者线程池中执行,最终会在run方法中执行eventBus.invokeSubscriber(pendingPost)方法。以上三步最终都会调用subscription.subscriberMethod.method.invoke(subscriptions.subscriber,eventObj),完成最终的执行,执行时subscriber注解标注的方法会被执行。

    3.我们接下来看下事件的接收,即用subscriber注解标注的方法。其实不用看这个方法,因为这个方法可以自定义只要符合规则就行。主要看一下Subscriber注解的定义和ThreadMode的定义加深对注解和线程模型的理解。

    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target({ElementType.METHOD})
    public @interface Subscribe {
        //指定订阅事件在哪个线程中运行,默认是POSTING,即在哪个线程中发送就在哪个线程中接收
        ThreadMode threadMode() default ThreadMode.POSTING;
        //粘性事件,默认为false
        boolean sticky() default false;
        //订阅事件执行的优先级
        int priority() default 0;
    }
    

      

    /**
     * EventBus线程模型
     */
    public enum ThreadMode {
        /**
         * 在哪个线程中发送事件就在哪个线程中接收事件
         */
        POSTING,
        /**
         * 如果实在主线程中发送事件就在主线程中处理,如果再子线程中发送事件就把事件先如队列,然后通过handler切换到主线程中处理
         */
        MAIN,
        /**
         * 无论在主线程还是子线程中发送事件,都将事件先入队列,然后通过Handler切换到主线程,依次处理事件。
         */
        MAIN_ORDERED,
        /**
         * 如果再主线程中发送事件,则将事件入队列,在线程池中依次执行。如果在子线程中发送事件,则直接在发送事件的线程中处理事件。
         */
        BACKGROUND,
        /**
         * 无论是在主线程还是在子线程中发送事件,都把时间入队列,通过线程池依次执行
         */
        ASYNC
    }
    

      不多说,注释非常的清晰了。

    4.接下来看一下事件是如何取消注册的,即EventBus.getDefault().unRegister(this)

      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 {
                logger.log(Level.WARNING, "Subscriber to unregister was not registered before: " + subscriber.getClass());
            }
        } 
       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--;
                    }
                }
            }
        }
    

      注册这块非常的简单就分两步:1.移除typesBySubscriber集合中的对象。2.通过eventType从subscriptionsByEventType中取出Subscriptions集合,然后找到和subscriber相等的Subscription.subscriber,然后将其从集合中移除掉就行了。

      

    总结:再总结一下这个三大流程做一个汇总

      1.注册

        注册是通过EventBus.getDefault().register(this)来完成的,

        a.其首先获取到订阅者subscriber的class对象。

        b.通过SubscriberMethodFinder对象的findSubscriberMethod获取订阅者方法集合(List<SubscriberMethod>),在这个方法中首先会根据subscriber.getClass为key检查METHOD_CACHE,Map集合中是否有缓存对象,如果有就直接返回,如果没有就解析subscriber.getClass()对象中用subscribe注解标注的方法,并从中取出Method、参数类型(eventType)、线程模型ThreadMode、是否是粘性事件、事件的优先级,并将这几个值封装到SubscriberMethod中,然后把SubscriberMethod对象存储到List<SubscriberMethod> subscriberMethods集合中,再以subscriber.getClass()为key,subscriberMethods为value存入METHOD_CACHE集合中,最后返回一个List<SubscriberMethod> subscriberMethods的集合。

        c.遍历subscriber集合并通过subscribe实现真正的订阅。在subscribe方法中会创建一个Subscription对象,并将subscriber和subscriberMethod存入Subscription对象,然后把Subscription对象存入CopyOnWriteArrayList<Subscription> subscriptions集合,并以subscription.subscriberMethod.eventType为key,subscriptions为value存入subscriptionsByEventType。以subscriber为key,List<Class<?>> subscribedEvents 为value将订阅者和事件类型关联到HashMap<subscriber,eventType> typesBySubscriber集合,到此注册订阅者就全部完成了。

      2.发送

        发送事件是从EventBus.getDefault().post(obj)开始的

        a.在post方法内部会首先初始化PostingThreadState(这个对象用ThreadLocal来存储的)。如:当前线程类型、队列等。然后会调用postSingleEvent方法,在postSingleEvent方法内部又会调用postSingleEventForEventType方法

        b.在postSingleEventForEventType方法内部会从subscriptionsByEventType集合中根据eventClass取出Subscriptions集合。然后循环遍历Subscriptions集合,并循环调用postToSubscription方法

        c.在postToSubscription方法内部会根据不同的线程模型执行不同的操作,如:MAIN,BACKGROUND等。最终都会调用eventBus.invokeSubscriber()方法,在invokeSubscriber内部会通过反射执行被subscriber注解标注过的方法,如:subscription.subscriberMethod.method.invoke(subscription.subscriber,eventObj).

      3.接收

        接收方法使用subscriber注解标注的自定义方法,非常简单,不再赘述。

      4.取消注册

        取消是通过EventBus.getDefault().unRegister(this)

        a.首先根据句subscriber对象拿到typesBySubscriber Map集合。并取出List<Class<?> subscriberTypes集合

        b.循环遍历subscriberTypes集合,然后以eventTypeClass为key从subscriptionsByEventType集合中获取到subscriptions集合。循环遍历subscriptions集合取出subscription.subscriber==subscriber相等的,然后移除掉缓存。

        c.根据subscriber为key,移除掉typesBySubscriber集合中的缓存的eventTypes集合。

        到此取消注册也就结束了。

     

  • 相关阅读:
    LinUI学习1 框架的引入
    LinUI学习2 config配置文件配置和使用
    LinUI学习3 Http请求封装与使用
    【网络编程】学习笔记02 套接字类型与协议设置
    【系统编程】 守护进程
    【网络编程】学习笔记03 地址族与数据序列
    【网络编程】学习笔记01 套接字与文件操作
    【系统编程】 进程间通信方式
    【网络编程】学习笔记06 I/O多路复用之epoll
    【网络编程】学习笔记04 server端和client代码
  • 原文地址:https://www.cnblogs.com/tony-yang-flutter/p/12459798.html
Copyright © 2011-2022 走看看