美文网首页
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