美文网首页
EventBus源码笔记

EventBus源码笔记

作者: 舌尖上的Android | 来源:发表于2018-03-01 09:59 被阅读0次

执行的线程,优先级,是否是粘性时间 @Subscribe(threadMode = ThreadMode.MAIN,priority = 100,sticky = true)
1 注册:
EventBus.Register(this);
2解绑:
EventBus.unRegister(this);
3接收

@Subscribe
public void func(eventBean event) {}

4发送

EventBus.post

register(obj) :
遍历传入的 class的所有方法,找到有Subscribe注解的所有方法 返回一个list

 public void register(Object subscriber) {   
 Class<?> subscriberClass = subscriber.getClass(); 
   List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
    synchronized (this) {
        for (SubscriberMethod subscriberMethod : subscriberMethods) { 
           subscribe(subscriber, subscriberMethod);​
        }
    }
}

findUsingReflectionInSingleClass 第一步:解析注册者对象的所有方法,并且找出带有注解subscribe注解的方法,然后通过annotation解析所有细节参数, 封装成一个对象,添加到集合,返回。

 findState.subscriberMethods.add(new SubscriberMethod(method, eventType, threadMode,        subscribeAnnotation.priority(), subscribeAnnotation.sticky()));

先从缓存中取
如果缓存中没有
ignoreGeneratedIndex:是否忽略注解生成器的MyEventBusIndex 默认false
默认走注解生成器
如果获取的列表为空,抛出异常
否则 返回list

List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
    List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);
    if (subscriberMethods != null) {
        return subscriberMethods;
    }

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

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();
        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)) {
                        ThreadMode threadMode = subscribeAnnotation.threadMode();
                        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");
        }
    }
}
private List<SubscriberMethod> getMethodsAndRelease(FindState findState) {
    List<SubscriberMethod> subscriberMethods = new ArrayList<>(findState.subscriberMethods);
    findState.recycle();
    synchronized (FIND_STATE_POOL) {
        for (int i = 0; i < POOL_SIZE; i++) {
            if (FIND_STATE_POOL[i] == null) {
                FIND_STATE_POOL[i] = findState;
                break;
            }
        }
    }
    return subscriberMethods;
}

最终装入缓存池,并返回对象

//—  .method.getParameterTypes  获取参数列表 
//method.setAccessible(true);  似有方法需要执行这句
Class a = Client.class;
try {
    Method method = a.getDeclaredMethod("a", int.class, int.class);
    System.out.println("----"+method.getParameterTypes().length + "-------“);//2
} catch (NoSuchMethodException e) {
    e.printStackTrace();
}

第二步:
subscribe() 解析所有SubscriberMethod的eventType,然后按照要求解析成
Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType的格式,
key是eventType
value就是subscription的列表,subscription包含两个对象的封装
如下

final class Subscription {
    final Object subscriber;//
    final SubscriberMethod subscriberMethod;//
    。。。
}

所以最终形成的map结构是这样:

    @Subscribe
    public void onRefresh(EventB event) {
    }
/*
subscriptionsByEventType 的key   就是  EventB.class   
Subscription  中的参数分别对应的 方法依托的类  ,以及具体的方法
*/
  synchronized (this) {
            for (SubscriberMethod subscriberMethod : subscriberMethods) {
                subscribe(subscriber, subscriberMethod);
            }
        }
    private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
        //eventType是方法参数的class
        Class<?> eventType = subscriberMethod.eventType;
        //再次封装对象,一个Subscription,对象中存入  :eg:activity实例,第二个是解析好的被注解的那个方法
        Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
        //subscriptionsByEventType 
        CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType);//一个map  key:对应的类    a
        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);
            }
        }

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

        List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);
        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<Class>).
                Set<Map.Entry<Class<?>, Object>> entries = stickyEvents.entrySet();
                for (Map.Entry<Class<?>, 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);
            }
        }
    }

post源码分析:待续

相关文章

网友评论

      本文标题:EventBus源码笔记

      本文链接:https://www.haomeiwen.com/subject/zbzwxftx.html