EventBusといくつかの考え

EventBusは、Androidの開発のための共通のフレームワークであり、それは賞賛のデカップリングという考えがあります

そのAndroidのSDKと登録されているどちらもBroadcastReceiver、のような、送信イベント、抗登録の面での特性から、EventBusを使用するように単純なように、イベントの優先順位を定義し、粘性(粘着性)イベントをサポートすることができますそしてより多くの、そしてクロスプロセスすることはできません

AndroidのSDKの事実は、機構--LocalBroadcastManager BroadcastReceiverクロスプロセスが存在しない、それだけで送信し、また、より高い類似性EventBusより高いレベルのセキュリティを有しており、従来のregisterBroadcastReceiver、と比較してこのプロセスでブロードキャストを受信することができます。

EventBusの基礎について、を参照してください。

EventBus

チュートリアル 高度な使い方の ソースの解析

ここでは、ソースコードと組み合わせて、EventBus学習と使用中の思考と注意に値するいくつかの場所を記録します。

登録

  1. どの方法が登録されるのですか?
  2. どのように同じオブジェクトの複数の登録をだろうか?
  3. どのようにオブジェクトを登録するには、注釈メソッドを購読しませんか?
  4. 親クラスが登録されている場合、オブジェクトの注釈付きメソッドを購読まだ登録されるのですか?
  5. 子クラスBは、親クラスAの楽しみのメソッドをオーバーライドする場合は、クラスBの子オブジェクトを呼び出すときに呼び出される?どのような方法で何が起こるかを登録しましたか?

これらの問題は、我々はregisterメソッドを分析する必要があります。

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);
        }
    }
}

上記第1の点コードの最初のルック。

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");
        }
    }
}

第2のレジスタ方法2ポイントで見て:

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);
        }
    }
    // ...
}

上記の質問5、コードは書いていないが、実際には、質問4の答えにサインアップするために探してたときに、資格の親クラスがポストコールの時に、登録され、回答されている、コールはそれを行うにはどの方法で、EventBusによってインボークメソッドへの反射が、当然、クラスのメソッドを達成することです。

イベントトリガー

  1. ポスト、eventTypeをどのように見つける該当する登録方法がない場合は?
  2. イベントは多型がそう呼ばれているラインでのEventType?
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));
        }
    }
}

アンチ登録

  1. 同じオブジェクトを複数回登録を解除、または非登録されたオブジェクトの登録を解除する方法?
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());
    }
}

おすすめ

転載: www.cnblogs.com/jamesvoid/p/12387602.html