EventBus and some thoughts

EventBus is a common framework for the development of Android, it is thought that decoupling of praise

From the characteristics in terms of its Android SDK and the like BroadcastReceiver, both of which are registered, send events, anti-registration, you can define the priority of the event and support the viscous (sticky) event, just as simple to use EventBus and more, and can not be cross-process

Android SDK fact, there is not a mechanism --LocalBroadcastManager BroadcastReceiver cross-process, it can only send and receive broadcasts in this process compared to conventional registerBroadcastReceiver, which has a higher level of security, and also higher similarity EventBus

About EventBus basis, please refer to:

EventBus

Tutorial Advanced Usage source parsing

Here combined with source code, record a few places worth thinking and attention in EventBus learning and use:

registered

  1. Which method will be registered?
  2. How will multiple registrations of the same object?
  3. Not how Subscribe annotation method to register an object?
  4. When the parent class is registered object Subscribe annotated method will be registered yet?
  5. If the child class B overrides the method of the parent class A fun, child objects of class B registered what happens? What kind of method is invoked when you call?

These problems, we need to analyze the register method:

public void register(Object subscriber) {
    Class<?> subscriberClass = subscriber.getClass();
    // 1. 找 subscriber 中被需要被注册的方法
    List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
    synchronized (this) {
        // 2. 注册这些方法
        for (SubscriberMethod subscriberMethod : subscriberMethods) {
            subscribe(subscriber, subscriberMethod);
        }
    }
}

First look at the first point code above;

List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
    // 缓存中取
    List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);
    if (subscriberMethods != null) {
        return subscriberMethods;
    }
    if (ignoreGeneratedIndex) {
        // 通过反射去找
        subscriberMethods = findUsingReflection(subscriberClass);
    } else {
        // 通过 Subscriber Index 去找,这里如果没找到,也会通过反射去找
        subscriberMethods = findUsingInfo(subscriberClass);
    }
    // 如果没有 找到被 Subscribe 注解的方法,抛出异常  ———— 问题 3
    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;
    }
}

// 继续分析注册方法的查找过程findUsingReflection
private List<SubscriberMethod> findUsingReflection(Class<?> subscriberClass) {
    FindState findState = prepareFindState();
    findState.initForSubscriber(subscriberClass);
    while (findState.clazz != null) {
        findUsingReflectionInSingleClass(findState);
        // 继续去 subscriberClass 的父类中找,但是这里有异常情况(几乎不会发生),往下看 ———— 问题 4
        findState.moveToSuperclass();
    }
    return getMethodsAndRelease(findState);
}
// findState.moveToSuperclass();
void moveToSuperclass() {
    if (skipSuperClasses) { // 异常情况,至于在哪里设置该标志位呢,继续往下看
        clazz = null;
    }
    // ...
}

// 继续分析注册方法的查找过程 findUsingReflectionInSingleClass
private void findUsingReflectionInSingleClass(FindState findState) {
    Method[] methods;
    // 先通过getDeclaredMethods查找,再通过getMethods查找
    try {
        methods = findState.clazz.getDeclaredMethods();
    } catch (Throwable th) {
        methods = findState.clazz.getMethods();
        // ...
        // 问题 4 的异常情况,在 getDeclaredMethods 发生异常时,跳过父类的注册方法查找
        findState.skipSuperClasses = true;
    }
    for (Method method : methods) {
        int modifiers = method.getModifiers();
        if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) {
            Class<?>[] parameterTypes = method.getParameterTypes();
            if (parameterTypes.length == 1) {
                Subscribe subscribeAnnotation = method.getAnnotation(Subscribe.class);
                if (subscribeAnnotation != null) {
                    Class<?> eventType = parameterTypes[0];
                    if (findState.checkAdd(method, eventType)) {
                        // 方法被注册的条件: public,被 Subscribe 注解,参数列表只有1个参数(也就是事件类型) ———— 问题 1
                        ThreadMode threadMode = subscribeAnnotation.threadMode();
                        findState.subscriberMethods.add(new SubscriberMethod(method, eventType, threadMode,
                                subscribeAnnotation.priority(), subscribeAnnotation.sticky()));
                    }
                }
            } else if (strictMethodVerification && method.isAnnotationPresent(Subscribe.class)) {
                // 在设置了 strictMethodVerification 时,如果 Subscribe 注解的方法参数个数不是 1,抛出异常,默认 strictMethodVerification标志是false,可以通过 EventBusBuilder 设置
                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)) {
            // 在设置了 strictMethodVerification 时,如果被 Subscribe 注解的方法不是 public,抛出异常
            String methodName = method.getDeclaringClass().getName() + "." + method.getName();
            throw new EventBusException(methodName +
                    " is a illegal @Subscribe method: must be public, non-static, and non-abstract");
        }
    }
}

Look in the second register method 2 points:

private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
    Class<?> eventType = subscriberMethod.eventType;
    Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
    CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
    if (subscriptions == null) {
        subscriptions = new CopyOnWriteArrayList<>();
        subscriptionsByEventType.put(eventType, subscriptions);
    } else {
        // 已经注册过了该 subscriber,再次注册抛出异常  ———— 问题 2
        if (subscriptions.contains(newSubscription)) {
            throw new EventBusException("Subscriber " + subscriber.getClass() + " already registered to event "
                    + eventType);
        }
    }
    // ...
}

Above Question 5, the code did not write, but in fact, in answer to Question 4 has been answered, when looking to sign up, qualified parent class will be registered, at the time of post call, the call is which way to do that, EventBus by reflection to invoke methods, naturally, is to achieve methods of the class;

Event trigger

  1. post, if there is no corresponding registration method eventType find how?
  2. EventType in line when the event is called polymorphism do?
private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {
    Class<?> eventClass = event.getClass();
    boolean subscriptionFound = false;
    // 设置了 eventInheritance 标志,查找 eventType 的 父类 和 父接口 的对应的事件类型,eventInheritance 标志默认为 true  ———— 问题 2
    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) {
        // 没有找到对应 eventType 的注册方法,先打个日志
        if (logNoSubscriberMessages) {
            logger.log(Level.FINE, "No subscribers registered for event " + eventClass);
        }
        // 如果设置了 sendNoSubscriberEvent 标志,post 一个 NoSubscriberEvent 事件  ———— 问题 1
        if (sendNoSubscriberEvent && eventClass != NoSubscriberEvent.class &&
                eventClass != SubscriberExceptionEvent.class) {
            post(new NoSubscriberEvent(this, event));
        }
    }
}

Anti-Registration

  1. Unregister the same object multiple times, or unregister a non-registered object how?
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 {
        // 没找到,就打了个日志  ———— 问题 1
        logger.log(Level.WARNING, "Subscriber to unregister was not registered before: " + subscriber.getClass());
    }
}

Guess you like

Origin www.cnblogs.com/jamesvoid/p/12387602.html