EventBus源码注释分析

EventBus源码分析

EventBus.java为主干开始

使用示例:

在MainActivity中我们写出如下方法,来做为事件响应回调方法,注意命名和参数即可

    //Event-------------------------start-------------------------------  
      /** 
       * 使用onEvent来接收事件,那么接收事件和分发事件在一个线程中执行 
       * @param event 
       */  
      public void onEvent(FirstEvent event)
      {  
        Log.d("yzy", "OnEvent-->"+Thread.currentThread().getId());  
      }  

      /** 
       * 使用onEventMainThread来接收事件,那么不论分发事件在哪个线程运行,接收事件永远在UI线程执行, 
       * 这对于android应用是非常有意义的 
       * @param event 
       */  
      public void onEventMainThread(MainEvent event)  
      {  
        Log.d("yzy", "onEventMainThread-->"+Thread.currentThread().getId());  
      }  

      /** 
       * 使用onEventBackgroundThread来接收事件,如果分发事件在子线程运行,那么接收事件直接在同样线程 
       * 运行,如果分发事件在UI线程,那么会启动一个子线程运行接收事件 
       * @param event 
       */  
      public void onEventBackgroundThread(BackEvent event)  
      {  
        Log.d("yzy", "onEventBackgroundThread-->"+Thread.currentThread().getId());  
      }  
      /** 
       * 使用onEventAsync接收事件,无论分发事件在(UI或者子线程)哪个线程执行,接收都会在另外一个子线程执行 
       * @param event 
       */  
      public void onEventAsync(AsyncEvent event)  
      {  
        Log.d("yzy", "onEventAsync-->"+Thread.currentThread().getId());  
      }  
      //Event------------------------------end------------------------------------- 

事件类FirstEvent,我们要产生事件,首先要产生事件类对象

public class FirstEvent{  
    private static final String TAG = "FirstEvent";  
    public String msg;  
    public FirstEvent(String msg){  
      this.msg=msg;  
    }

    public String getMsg(){
        return msg;
    }
} 

我们在另外一个SecondActivity中post事件去通知MainActivity的onEvent开头的方法

在MainActivity中注册register

EventBus.getDefault().register(this);  

在SecondActivity中post事件

EventBus.getDefault().post(new FirstEvent());

全局变量释义

// 以EventType(如FirstEvent.getClass();)为key,存储所有订阅信息的Map(CopyOnWriteArrayList支持多线程遍历和增删)
private final Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType;
// 保存了所有订阅者订阅的事件集合
private final Map<Object, List<Class<?>>> typesBySubscriber;
// stick类型事件集合,以eventType的class为key保存,value为eventType
private final Map<Class<?>, Object> stickyEvents;

register过程

订阅流程图

图片来自codeKK

注册register(或订阅事件)

    // 注册方法
    private synchronized void register(Object subscriber, boolean sticky, int priority) {
        // 取出订阅者所有事件响应方法,循环遍历每一个方法,并调用subscribe方法
        List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriber.getClass());
        for (SubscriberMethod subscriberMethod : subscriberMethods) {
            subscribe(subscriber, subscriberMethod, sticky, priority);
        }
    }

查找订阅者响应函数

    /**
     * 查找订阅者响应函数,如果不在缓存中,则遍历自己的每个函数并递归父类查找,查找成功后保存到缓存中
     * @param subscriberClass   订阅者类的字节码(比如MainActivity.class)
     * @return List<SubscriberMethod> 订阅者(比如MainActivity)所有的事件响应函数信息的集合
     */
    List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
        // 比如MainActivity.class.getName ==> "cn.jason.activity.MainActivity"
        String key = subscriberClass.getName();
        List<SubscriberMethod> subscriberMethods;
        synchronized (methodCache) {
            subscriberMethods = methodCache.get(key);
        }
        if (subscriberMethods != null) {
            return subscriberMethods;
        }
        // 没有在方法缓存中,新建
        subscriberMethods = new ArrayList<SubscriberMethod>();
        Class<?> clazz = subscriberClass;
        HashSet<String> eventTypesFound = new HashSet<String>();
        StringBuilder methodKeyBuilder = new StringBuilder();
        while (clazz != null) {
            String name = clazz.getName();  // name ==> "cn.jason.activity.MainActivity"
            if (name.startsWith("java.") || name.startsWith("javax.") || name.startsWith("android.")) {
                // 跳过影响性能的系统类,比如 "java.lang.String"
                break;
            }

            // Starting with EventBus 2.2 we enforced methods to be public (might change with annotations again)
            Method[] methods = clazz.getDeclaredMethods();
            for (Method method : methods) {
                String methodName = method.getName();
                if (methodName.startsWith(ON_EVENT_METHOD_NAME)) {
                    int modifiers = method.getModifiers();
                    // MODIFIERS_IGNORE = 0000 0111 1110 1000, 修饰符不是ignore中的某个,并且是public的
                    if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) {
                        Class<?>[] parameterTypes = method.getParameterTypes();
                        // 参数类型数组个数代表有几个参数,只有一个参数符合要求
                        if (parameterTypes.length == 1) {
                            // 从"onEvent"之后截取方法名,由方法名来判断出threadMode(我们主观确定要使用的线程模式),后续结合代码实际运行在主线程还是在子线程,来共同决定处理事件方法的方式。
                            String modifierString = methodName.substring(ON_EVENT_METHOD_NAME.length());
                            ThreadMode threadMode;
                            if (modifierString.length() == 0) {
                                threadMode = ThreadMode.PostThread;
                            } else if (modifierString.equals("MainThread")) {
                                threadMode = ThreadMode.MainThread;
                            } else if (modifierString.equals("BackgroundThread")) {
                                threadMode = ThreadMode.BackgroundThread;
                            } else if (modifierString.equals("Async")) {
                                threadMode = ThreadMode.Async;
                            } else {
                                // skipMethodVerificationForClasses:跳过方法验证的类集合,比如MainActivity中有包含非事件响应方法的以onEvent开头的方法(onEventXXX)
                                if (skipMethodVerificationForClasses.containsKey(clazz)) {
                                    continue;
                                } else {
                                    throw new EventBusException("Illegal onEvent method, check for typos: " + method);
                                }
                            }
                            // 唯一的参数,作为eventType对象
                            Class<?> eventType = parameterTypes[0];
                            methodKeyBuilder.setLength(0);
                            methodKeyBuilder.append(methodName);
                            methodKeyBuilder.append('>').append(eventType.getName());
                            String methodKey = methodKeyBuilder.toString();
                            if (eventTypesFound.add(methodKey)) {
                                // 只添加在子类中没有被发现过的方法,eventTypesFound的左右只是临时存放,判断该方法是否被添加过
                                subscriberMethods.add(new SubscriberMethod(method, threadMode, eventType));
                            }
                        }
                    } else if (!skipMethodVerificationForClasses.containsKey(clazz)) {
                        Log.d(EventBus.TAG, "Skipping method (not public, static or abstract): " + clazz + "."
                                    + methodName);
                    }
                }
            }
            // 寻找其父类中的方法
            clazz = clazz.getSuperclass();
        }
        if (subscriberMethods.isEmpty()) {
            throw new EventBusException("Subscriber " + subscriberClass + " has no public methods called "
                        + ON_EVENT_METHOD_NAME);
        } else {
            synchronized (methodCache) {
                methodCache.put(key, subscriberMethods);
            }
            return subscriberMethods;
        }
    }

subscribe订阅方法

    // 必须被放在同步代码块中使用
    private void subscribe(Object subscriber, SubscriberMethod subscriberMethod, boolean sticky, int priority) {
        // 响应方法的事件类型(MainActivity中有个onEvent(new FirstEvent()),此处的eventType就是FirstEvent.class)
        Class<?> eventType = subscriberMethod.eventType;
        // 以eventType为key,在subscriptionsByEventType中取出订阅信息的集合subscriptions
        CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
        // 使用订阅者、事件响应方法、优先级创建一个订阅信息对象
        Subscription newSubscription = new Subscription(subscriber, subscriberMethod, priority);
        if (subscriptions == null) {
            // 如果取出的订阅信息集合为空,创建一个集合,并且一此事件类型为key,存入该集合中
            subscriptions = new CopyOnWriteArrayList<Subscription>();
            subscriptionsByEventType.put(eventType, subscriptions);
        } else {
            // 取出订阅信息集合不为空,并且已经包含了这个订阅信息,则抛出异常,说明已经注册了这个对象,不能重复register
            if (subscriptions.contains(newSubscription)) {
                throw new EventBusException("Subscriber " + subscriber.getClass() + " already registered to event "
                            + eventType);
            }
        }

        // Starting with EventBus 2.2 we enforced methods to be public (might change with annotations again)
        // subscriberMethod.method.setAccessible(true);

        // 对比priority,添加新register的订阅信息到集合subscriptions中
        int size = subscriptions.size();
        for (int i = 0; i <= size; i++) {
            if (i == size || newSubscription.priority > subscriptions.get(i).priority) {
                // 集合中已经是按照priority排过序的了,所以从头开始比较,只要大于了,则直接插入即可,后续的肯定都比它更小了
                subscriptions.add(i, newSubscription);
                break;
            }
        }

        // typesBySubscriber保存了所有订阅者订阅的事件集合,此处是将此次subscribe的方法加入到此订阅者相应的集合中去
        List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);
        if (subscribedEvents == null) {
            subscribedEvents = new ArrayList<Class<?>>();
            typesBySubscriber.put(subscriber, subscribedEvents);
        }
        subscribedEvents.add(eventType);

        // 如果为sticky的处理,则从stickyEvents事件保存集合中取出该事件类型最后一个事件发送给当前订阅者。
        if (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();
                    // entries内部应该是按照时间排序的,第一次循环到的合适的eventType的子类就是最后一个发送的eventType
                    if (eventType.isAssignableFrom(candidateEventType)) {
                        Object stickyEvent = entry.getValue();
                        checkPostStickyEventToSubscription(newSubscription, stickyEvent);
                    }
                }
            } else {
                Object stickyEvent = stickyEvents.get(eventType);
                checkPostStickyEventToSubscription(newSubscription, stickyEvent);
            }
        }
    }

    private void checkPostStickyEventToSubscription(Subscription newSubscription, Object stickyEvent) {
        if (stickyEvent != null) {
            // If the subscriber is trying to abort the event, it will fail (event is not tracked in posting state)
            // --> Strange corner case, which we don't take care of here.
            postToSubscription(newSubscription, stickyEvent, Looper.getMainLooper() == Looper.myLooper());
        }
    }

postToSubscription发送订阅事件到订阅信息指定的对象

    private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {
        switch (subscription.subscriberMethod.threadMode) {
            case PostThread:
                invokeSubscriber(subscription, event);
                break;
            case MainThread:
                if (isMainThread) {
                    invokeSubscriber(subscription, event);
                } else {
                    mainThreadPoster.enqueue(subscription, event);
                }
                break;
            case BackgroundThread:
                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);
        }
    }

post过程

post

post

/** 将传入的event发布到event bus */
public void post(Object event) {
    PostingThreadState postingState = currentPostingThreadState.get();
    List<Object> eventQueue = postingState.eventQueue;
    eventQueue.add(event);

    // 是否正在执行着,如果正在执行,刚被添加的event也会自动被其他EventBus对象执行到,因为一个线程只有一个eventQueue
    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 {
            while (!eventQueue.isEmpty()) {
                // 发布队列中的每一个事件
                postSingleEvent(eventQueue.remove(0), postingState);
            }
        } finally {
            postingState.isPosting = false;
            postingState.isMainThread = false;
        }
    }
}

postSingleEvent

    // 发布队列中的每一个事件
    private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {
        Class<?> eventClass = event.getClass();
        boolean subscriptionFound = false;
        if (eventInheritance) {
            // 如果是可以继承的event,查找到其继承关系
            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) {
                Log.d(TAG, "No subscribers registered for event " + eventClass);
            }
            if (sendNoSubscriberEvent && eventClass != NoSubscriberEvent.class &&
                    eventClass != SubscriberExceptionEvent.class) {
                post(new NoSubscriberEvent(this, event));
            }
        }
    }

postSingleEventForEventType

    // 发布每个事件到每个订阅者
    private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class<?> eventClass) {
        CopyOnWriteArrayList<Subscription> subscriptions;
        synchronized (this) {
            subscriptions = subscriptionsByEventType.get(eventClass);
        }
        if (subscriptions != null && !subscriptions.isEmpty()) {
            // 遍历所有此eventType事件的注册信息
            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

    // 根据订阅信息及对应的事件,调用相应方法
    private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {
        switch (subscription.subscriberMethod.threadMode) {
            case PostThread:
                invokeSubscriber(subscription, event);
                break;
            case MainThread:
                if (isMainThread) {
                    invokeSubscriber(subscription, event);
                } else {
                    mainThreadPoster.enqueue(subscription, event);
                }
                break;
            case BackgroundThread:
                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);
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值