目录

一、添加gradle依赖

二、基础操作

1、EventBus.getDefault();    

2、EventBus.getDefault().register(this);  

3、EventBus.getDefault().post(object);  

4、EventBus.getDefault().unregister();  

二、四个onEvent方法

三、EventBus3.0

四、原理简述


定义

EventBus是一款在 Android 开发中使用的发布、订阅事件总线框架,基于观察者模式,将事件的接收者和发送者分开,可以在Activity、Fragment、Service等组件交互通信,使用简单、效率高、体积小。

可以替代Intent、Broadcast、Thread+Handle异步线程间传递消息。

githup地址:https://github.com/greenrobot/EventBus

一、添加gradle依赖

 

implementation 'org.greenrobot:eventbus:3.1.1'

 

二、基础操作

1、EventBus.getDefault();    

getDefault是一个单例方法,保证返回唯一的EventBus实例对象。

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

2、EventBus.getDefault().register(this);  

public void register(Object subscriber) {        // 反射获取当前注册类的Class对象        Class<?> subscriberClass = subscriber.getClass();        // 1、查找:根据Class查找当前类中订阅了事件的方法集合        List subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);        synchronized (this) {            // 2、注册:循环遍历订阅了事件的方法集合,以完成注册            for (SubscriberMethod subscriberMethod : subscriberMethods) {                subscribe(subscriber, subscriberMethod);            }        }    }

主要分为查找和注册两部分,首先来看查找的过程,从findSubscriberMethods()开始: 

List findSubscriberMethods(Class<?> subscriberClass) {        // METHOD_CACHE是一个ConcurrentHashMap,直接保存了subscriberClass和对应SubscriberMethod的集合,以提高注册效率,赋值重复查找。        List subscriberMethods = METHOD_CACHE.get(subscriberClass);        if (subscriberMethods != null) {            return subscriberMethods;        }        // 由于使用了默认的EventBusBuilder,则ignoreGeneratedIndex属性默认为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;        }    }

先从缓存中查找,如果找到则直接返回,否则去做下一步的查找过程,然后缓存查找到的集合,根据上边的注释可知findUsingInfo()方法会被调用: 

private List findUsingInfo(Class<?> subscriberClass) {        FindState findState = prepareFindState();        findState.initForSubscriber(subscriberClass);        // 初始状态下findState.clazz就是subscriberClass        while (findState.clazz != null) {            findState.subscriberInfo = getSubscriberInfo(findState);            // 条件不成立            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为subscriberClass的父类Class,即需要遍历父类            findState.moveToSuperclass();        }        // 查找到的方法保存在了FindState实例的subscriberMethods集合中。        // 使用subscriberMethods构建一个新的List        // 释放掉findState        return getMethodsAndRelease(findState);    }

findUsingInfo()方法会在当前要注册的类以及其父类中查找订阅事件的方法,这里出现了一个FindState类,它是SubscriberMethodFinder的内部类,用来辅助查找订阅事件的方法,具体的查找过程在findUsingReflectionInSingleClass()方法,它主要通过反射查找订阅事件的方法: 

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类型,但非abstract、static等            if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) {                // 获得当前方法所有参数的类型                Class<?>[] parameterTypes = method.getParameterTypes();                // 如果当前方法只有一个参数                if (parameterTypes.length == 1) {                    Subscribe subscribeAnnotation = method.getAnnotation(Subscribe.class);                    // 如果当前方法使用了Subscribe注解                    if (subscribeAnnotation != null) {                        // 得到该参数的类型                        Class<?> eventType = parameterTypes[0];                        // checkAdd()方法用来判断FindState的anyMethodByEventType map是否已经添加过以当前eventType为key的键值对,没添加过则返回true                        if (findState.checkAdd(method, eventType)) {                             // 得到Subscribe注解的threadMode属性值,即线程模式                            ThreadMode threadMode = subscribeAnnotation.threadMode();                            // 创建一个SubscriberMethod对象,并添加到subscriberMethods集合                            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)) {                String methodName = method.getDeclaringClass().getName() + "." + method.getName();                throw new EventBusException(methodName +                        " is a illegal @Subscribe method: must be public, non-static, and non-abstract");            }        }    }

 

到此register()方法中findSubscriberMethods()流程就分析完了,我们已经找到了当前注册类及其父类中订阅事件的方法的集合。接下来分析具体的注册流程,即register()中的subscribe()方法:

private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {        // 得到当前订阅了事件的方法的参数类型        Class<?> eventType = subscriberMethod.eventType;        // Subscription类保存了要注册的类对象以及当前的subscriberMethod        Subscription newSubscription = new Subscription(subscriber, subscriberMethod);        // subscriptionsByEventType是一个HashMap,保存了以eventType为key,Subscription对象集合为value的键值对        // 先查找subscriptionsByEventType是否存在以当前eventType为key的值        CopyOnWriteArrayList subscriptions = subscriptionsByEventType.get(eventType);        // 如果不存在,则创建一个subscriptions,并保存到subscriptionsByEventType        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;            }        }        // typesBySubscribere也是一个HashMap,保存了以当前要注册类的对象为key,注册类中订阅事件的方法的参数类型的集合为value的键值对        // 查找是否存在对应的参数类型集合        List> subscribedEvents = typesBySubscriber.get(subscriber);        // 不存在则创建一个subscribedEvents,并保存到typesBySubscriber        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).                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);            }        }    }

这就是注册的核心流程,所以subscribe()方法主要是得到了subscriptionsByEventTypetypesBySubscriber两个 HashMap。我们在发送事件的时候要用到subscriptionsByEventType,完成事件的处理。当取消 EventBus 注册的时候要用到typesBySubscribersubscriptionsByEventType,完成相关资源的释放。 

3、EventBus.getDefault().post(object);  

public void post(Object event) {        //事件队列和线程模式等信息        PostingThreadState postingState = currentPostingThreadState.get();        List 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()方法先将发送的事件保存的事件队列,然后通过循环出队列,将事件交给postSingleEvent()方法处理:

private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {        Class<?> eventClass = event.getClass();        boolean subscriptionFound = false;        // eventInheritance默认为true,表示是否向上查找事件的父类        if (eventInheritance) {            // 查找当前事件类型的Class,连同当前事件类型的Class保存到集合            List> eventTypes = lookupAllEventTypes(eventClass);            int countTypes = eventTypes.size();            // 遍历Class集合,继续处理事件            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));            }        }    }

postSingleEvent()方法中,根据eventInheritance属性,决定是否向上遍历事件的父类型,然后用postSingleEventForEventType()方法进一步处理事件:

private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class<?> eventClass) {        CopyOnWriteArrayList subscriptions;        synchronized (this) {            // 获取事件类型对应的Subscription集合            subscriptions = subscriptionsByEventType.get(eventClass);        }        // 如果已订阅了对应类型的事件        if (subscriptions != null && !subscriptions.isEmpty()) {            for (Subscription subscription : subscriptions) {                // 记录事件                postingState.event = event;                // 记录对应的subscription                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;    }

postSingleEventForEventType()方法核心就是遍历发送的事件类型对应的Subscription集合,然后调用postToSubscription()方法处理事件。 

4、EventBus.getDefault().unregister();  

public synchronized void unregister(Object subscriber) {        // 得到当前注册类对象 对应的 订阅事件方法的参数类型 的集合        List> subscribedTypes = typesBySubscriber.get(subscriber);        if (subscribedTypes != null) {            // 遍历参数类型集合,释放之前缓存的当前类中的Subscription            for (Class<?> eventType : subscribedTypes) {                unsubscribeByEventType(subscriber, eventType);            }            // 删除以subscriber为key的键值对            typesBySubscriber.remove(subscriber);        } else {            logger.log(Level.WARNING, "Subscriber to unregister was not registered before: " + subscriber.getClass());        }    }private void unsubscribeByEventType(Object subscriber, Class<?> eventType) {        // 得到当前参数类型对应的Subscription集合        List subscriptions = subscriptionsByEventType.get(eventType);        if (subscriptions != null) {            int size = subscriptions.size();            // 遍历Subscription集合            for (int i = 0; i < size; i++) {                Subscription subscription = subscriptions.get(i);                // 如果当前subscription对象对应的注册类对象 和 要取消注册的注册类对象相同,则删除当前subscription对象                if (subscription.subscriber == subscriber) {                    subscription.active = false;                    subscriptions.remove(i);                    i--;                    size--;                }            }        }    }

unregister()方法中,释放了typesBySubscribersubscriptionsByEventType中缓存的资源。 

二、四个onEvent方法

  • onEventMainThread

代表这个方法会在UI线程执行

  • onEventPostThread

代表这个方法会在当前线程执行

  • onEventBackgroundThread

代表非UI线程会在同线程执行,是的话在后台执行,一个一个调用。

  • onEventAsync

代表加入后台任务,使用线程池调用,不是一个一个调用。

三、EventBus3.0

开始使用Subscribe注解配置事件订阅方法,可以指定threadModestickypriority三个属性。源码如下

@Documented@Retention(RetentionPolicy.RUNTIME)@Target({ElementType.METHOD})public @interface Subscribe {    // 指定事件订阅方法的线程模式,即在那个线程执行事件订阅方法处理事件,默认为POSTING    ThreadMode threadMode() default ThreadMode.POSTING;    // 是否支持粘性事件,默认为false    boolean sticky() default false;    // 指定事件订阅方法的优先级,默认为0,如果多个事件订阅方法可以接收相同事件的,则优先级高的先接收到事件    int priority() default 0;}

其中,threadMode属性有如下几个可选值:

  • ThreadMode.POSTING

默认的线程模式,在那个线程发送事件就在对应线程处理事件,避免了线程切换,效率高。

  • ThreadMode.MAIN

如在主线程(UI线程)发送事件,则直接在主线程处理事件;如果在子线程发送事件,则先将事件入队列,然后通过 Handler 切换到主线程,依次处理事件。

  • ThreadMode.MAIN_ORDERED

无论在那个线程发送事件,都先将事件入队列,然后通过 Handler 切换到主线程,依次处理事件。

  • ThreadMode.BACKGROUND

如果在主线程发送事件,则先将事件入队列,然后通过线程池依次处理事件;如果在子线程发送事件,则直接在发送事件的线程处理事件。

  • ThreadMode.ASYNC

无论在那个线程发送事件,都将事件入队列,然后通过线程池处理。

四、原理简述

EventBus内部封装4个onEvent方法,然后post发送事件的时候,根据post参数类型自动匹配执行的方法。register(this)订阅在当前类,通过反射调用遍历当前类所有的方法,找到onEvent开发的方法,然后进行Map存储,key为class类型,值为对象实例。

 

 

更多相关文章

  1. Android(安卓)JVM的运行过程
  2. android开发之onCreate( )方法详解
  3. Android(安卓)桌面悬浮框
  4. android设置手机横屏与竖屏无效的解决方法
  5. Android(安卓)4.0源代码windows平台下载方法
  6. Retrofit2使用方式和源码解析
  7. Android-微信抢红包插件-原理分析
  8. android 常用混淆
  9. Android视图加载流程(2)之Window和WindowManager的创建与Activit

随机推荐

  1. Android应用程序版本号管理(官方文档中文
  2. Android资源访问
  3. Android下使用lamemp3库将PCM录音数据压
  4. Android之如果解决Android(安卓)studio项
  5. ListView中显示圆形图像
  6. android Input系统事件分发流程
  7. Android回部古剑之ViewFlipper之仙人指路
  8. Android开发 ADB配置调试命令图解
  9. Android原理揭秘系列之View、ViewGroup
  10. WebView 使用Android(安卓)原生ToolBar