zoukankan      html  css  js  c++  java
  • 【第五篇】androidEventbus源代码阅读和分析之发送粘性事件和接收粘性事件代码分析

    代码里面发送粘性事件代码如下:

    1. //  发送Sticky事件
              EventBus.getDefault().postSticky(new User("soyoungboy", "西安财经学院"),
                      "soyoungboy");

    然后我们进入postSticky方法里面去:
    EventType 是什么?
    该类是描述一个函数唯一性的对象,参数类型、tag两个条件保证了对象的唯一性.通过该类的对象来查找注册了相应类型和tag的所有订阅者{@see* Subscription}, 并且在接到消息时调用所有订阅者对应的函数. 
    mStickyEvents是什么?
    1.  private List<EventType> mStickyEvents = Collections
                  .synchronizedList(new LinkedList<EventType>());

    是个list集合,用于存储eventType的list集合。
    1.  /**
           * 发布Sticky事件,tag为EventType.DEFAULT_TAG
           * 
           * @param event
           */
          public void postSticky(Object event) {
              postSticky(event, EventType.DEFAULT_TAG);
          }
          /**
           * 发布含有tag的Sticky事件
           * 
           * @param event 事件
           * @param tag 事件tag
           */
          public void postSticky(Object event, String tag) {
              EventType eventType = new EventType(event.getClass(), tag);
              eventType.event = event;
              mStickyEvents.add(eventType);
              // 处理sticky事件
      //        mDispatcher.handleStickyEvent(eventType, null);
          }
    这是发布,如何接收粘性事件,我们也看下源码来分析下:
    首先要注册粘性事件的eventbus:
    1. EventBus.getDefault().registerSticky(this);
    走进registerSticky代码里面看下:
    1.  /**
           * 以sticky的形式注册,则会在注册成功之后迭代所有的sticky事件
           * 
           * @param subscriber
           */
          public void registerSticky(Object subscriber) {
              this.register(subscriber);
              // 处理sticky事件
              mDispatcher.dispatchStickyEvents(subscriber);
          }

      register代码不进行分析,因为前面讲过,就是将@ subscriber的订阅者对象放入map集合里面去

    重点分析下 mDispatcher.dispatchStickyEvents(subscriber);
    1.  void dispatchStickyEvents(Object subscriber) {
                  for (EventType eventType : mStickyEvents) {
                      handleStickyEvent(eventType, subscriber);
                  }
              }

    在往下面走:
    根据不同的ThreadMode去调用不同的handler(这里是事件分发器对象)的handleEvent方法。
    ThreadMode是在代码里面通过注解传进来的。
    /**
             * 处理单个Sticky事件
             * 
             * @param eventType
             * @param aEvent
             */
            private void handleStickyEvent(EventType eventType, Object subscriber) {
                //从缓存获取eventTypes内容
                List<EventType> eventTypes = getMatchedEventTypes(eventType, eventType.event);
                // 事件
                Object event = eventType.event;
                //循环遍历eventType集合
                for (EventType foundEventType : eventTypes) {
                    Log.e("", "### 找到的类型 : " + foundEventType.paramClass.getSimpleName()
                            + ", event class : " + event.getClass().getSimpleName());
                    //从订阅者的map集合里面获取指定的订阅者集合的list集合,根据eventType
                    final List<Subscription> subscriptions = mSubcriberMap.get(foundEventType);
                    if (subscriptions == null) {
                        continue;
                    }
                    //遍历list集合
                    for (Subscription subItem : subscriptions) {
                        final ThreadMode mode = subItem.threadMode;
                        EventHandler eventHandler = getEventHandler(mode);
                        // 如果订阅者为空,那么该sticky事件分发给所有订阅者.否则只分发给该订阅者
                        if (isTarget(subItem, subscriber)
                                && (subItem.eventType.equals(foundEventType)
                                        || subItem.eventType.paramClass
                                        .isAssignableFrom(foundEventType.paramClass))) {
                            // 处理事件
                            eventHandler.handleEvent(subItem, event);
                        }
                    }
                }
            }
    mDispatcher是个事件分发器;
    EventDispatcher事件分发器中有三条个ThreadEventHandler:
    UIThreadEventHandler
    DefaultEventHandler
    AsyncEventHandler
    都实现了EventHandler事件处理接口,实现handleEvent方法:
    UIThreadEventHandler中实现:
    事件处理在UI线程,通过Handler将事件处理post到UI线程的消息队列,UIThreadEventHandler的handleEvent指向DefaultEventHandler的handleEvent方法;  
    1. /**
           * @param subscription
           * @param event
           */
          public void handleEvent(final Subscription subscription, final Object event) {
              mUIHandler.post(new Runnable() {
                  @Override
                  public void run() {
                      mEventHandler.handleEvent(subscription, event);
                  }
              });
          }

     
    AsyncEventHandler中实现:默认也是子类为DefaultEventHandler的handleEvent去实现,重点还是DefaultEventHandler中的handleEvent的实现。
    1.  /**
           * 将订阅的函数执行在异步线程中
           * 
           * @param subscription
           * @param event
           */
          public void handleEvent(final Subscription subscription, final Object event) {
              mDispatcherThread.post(new Runnable() {
                  @Override
                  public void run() {
                      mEventHandler.handleEvent(subscription, event);
                  }
              });
          }

    DefaultEventHandler中实现:
    重点是subscription.targetMethod.invoke(subscription.subscriber.get(), event),代码走到最后走到这里,那么到这这里执行了什么操作呢;
    执行反射操作,根据参数查找方法,进行反射调用。
     /**
         * handle the event
         * 
         * @param subscription
         * @param event
         */
        public void handleEvent(Subscription subscription, Object event) {
            if (subscription == null
                    || subscription.subscriber.get() == null) {
                return;
            }
            try {
                // 执行
                subscription.targetMethod.invoke(subscription.subscriber.get(), event);
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        }
  • 相关阅读:
    JavaScript npm/nrm 切换安装依赖的镜像源
    Vue Vuex中的严格模式/实例解析/dispatch/commit /state/getters
    Vuex mapGetter的基本使用
    Springboot 整合Mybatis-plus
    SEO基本功:站内优化的一些基本手段
    解决使用logstash中jdbc导入mysql中的数据到elasticsearch中tinyint类型被转成布尔型的问题的方法
    【重大好消息】elasticsearch 7.3版本已经可以免费使用x-pack就可以设置账号和密码了,让你的数据不再裸奔
    elasticsearch7.3版本已经不需要额外安装中文分词插件了
    网络案例分析之999皮炎平出鹤顶红色号的口红
    php框架symfony踩坑苦旅(1)
  • 原文地址:https://www.cnblogs.com/androidsuperman/p/4679982.html
Copyright © 2011-2022 走看看