美文网首页
EventBus3.0源码分析记录

EventBus3.0源码分析记录

作者: wenou | 来源:发表于2017-11-07 18:21 被阅读14次

    简单使用

    1. 注册
    EventBus.getDefault().register(this);
    
    1. 声明方法(post发送事件的时候,反射调用),不能是private 类型的方法,否则在编译的时候会报错.可以在@Subscribe(threadMode = ThreadMode.MAIN)指定接收事件的时候运行的线程.如果不写,默认是ThreadMode.POSTING
    @Subscribe
    public void busMethod(String s){
        Log.d(TAG, "busMethod: " + s);
    }
    
    @Subscribe(threadMode = ThreadMode.MAIN)
    protected void busMethod(Object obj){
            
    }
    
    1. 发送事件,可以传递任何数据类型,对象需要序列化
    EventBus.getDefault().post("test obj");
    
    1. 注销注册
    EventBus.getDefault().unregister(this);
    
    四种threadMode

    1. ThreadMode.POSTING
    post发送事件是在什么线程,接收就在什么线程

    2. ThreadMode.MAIN
    post发送事件不管在什么线程,接收肯定在主线程(UI线程)

    3. ThreadMode.BACKGROUND
    post发送事件不管在什么线程,接收肯定在子线程

    4. ThreadMode.ASYNC
    post不管在什么线程,都会创建新的子线程来接收.

    EventBus.getDefault()源码

    EventBus(EventBusBuilder builder) {
            //以订阅方法参数类型为key,订阅的类和方法的封装为value
            subscriptionsByEventType = new HashMap<>();
            typesBySubscriber = new HashMap<>();//记录订阅的对象,和方法的参数类型
            stickyEvents = new ConcurrentHashMap<>();
            mainThreadPoster = new HandlerPoster(this, Looper.getMainLooper(), 10);//主线程Handler
            backgroundPoster = new BackgroundPoster(this);//子线程Handler
            asyncPoster = new AsyncPoster(this);//处理ThreadMode.ASYNC的Handler
    
            indexCount = builder.subscriberInfoIndexes != null ? builder.subscriberInfoIndexes.size() : 0;
            subscriberMethodFinder = new SubscriberMethodFinder(builder.subscriberInfoIndexes,
                    builder.strictMethodVerification, builder.ignoreGeneratedIndex);
            logSubscriberExceptions = builder.logSubscriberExceptions;
            logNoSubscriberMessages = builder.logNoSubscriberMessages;
            sendSubscriberExceptionEvent = builder.sendSubscriberExceptionEvent;
            sendNoSubscriberEvent = builder.sendNoSubscriberEvent;
            throwSubscriberException = builder.throwSubscriberException;
            eventInheritance = builder.eventInheritance; //默认是 true
            executorService = builder.executorService;//线程池
        }
    

    EventBus.getDefault的时候是进行了一些数据的初始化

    register源码

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

    通过findSubscriberMethods方法,找到注册类中用来接收消息的方法,

    findSubscriberMethods

    List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
            //如果有缓存,直接返回
            List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);
            if (subscriberMethods != null) {
                return subscriberMethods;
            }
    
            if (ignoreGeneratedIndex) { //默认是false
                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;
            }
        }
    

    这里有用Map<Class<?>, List<SubscriberMethod>> METHOD_CACHEMap集合把该类的接收事件方法缓存,避免下次重复处理,ignoreGeneratedIndex 默认是false,进入findUsingInfo方法

    findUsingInfo

    private List<SubscriberMethod> findUsingInfo(Class<?> subscriberClass) {
            FindState findState = prepareFindState();//创建FindState 来记录方法的一些信息
            findState.initForSubscriber(subscriberClass);
            while (findState.clazz != null) {
                findState.subscriberInfo = getSubscriberInfo(findState);
                if (findState.subscriberInfo != null) {  //默认是null
                    SubscriberMethod[] array = findState.subscriberInfo.getSubscriberMethods();
                    for (SubscriberMethod subscriberMethod : array) {
                        if (findState.checkAdd(subscriberMethod.method, subscriberMethod.eventType)) {
                            findState.subscriberMethods.add(subscriberMethod);
                        }
                    }
                } else {
                    //走到这里
                    findUsingReflectionInSingleClass(findState);
                }
                findState.moveToSuperclass();
            }
            return getMethodsAndRelease(findState);
        }
    

    findState.subscriberInfo默认是null,所以就走到findUsingReflectionInSingleClass()方法

    findUsingReflectionInSingleClass

    private void findUsingReflectionInSingleClass(FindState findState) {
            Method[] methods;
            try {
                methods = findState.clazz.getDeclaredMethods();//获取该类所有的方法
            } catch (Throwable th) {
                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注释
                        Subscribe subscribeAnnotation = method.getAnnotation(Subscribe.class); 
                        if (subscribeAnnotation != null) {  //@Subscribe注释不为 null 才满足
                            Class<?> eventType = parameterTypes[0];
                            if (findState.checkAdd(method, eventType)) {
    
                                //获取接收事件方法的 threadMode 类型
                                ThreadMode threadMode = subscribeAnnotation.threadMode();
    
                                //把方法名,参数类型, threadMode类型都封装到SubscriberMethod对象,用findState来管理
                                findState.subscriberMethods.add(new SubscriberMethod(method, eventType, threadMode,
                                        subscribeAnnotation.priority(), subscribeAnnotation.sticky()));
                            }
                        }
                   ...
        }
    

    这里就是找到注册类中具体的方法,进行一些封装并且记录起来,然后结束这个方法,进入到return getMethodsAndRelease(findState);最后一个方法,返回一个List<SubscriberMethod>集合

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

    getMethodsAndRelease() 方法就是清空findState对象里面的一些数据,释放内存,并且这里使用了FindState[] FIND_STATE_POOL ,FindState[] 数组来循环利用,避免销毁更多的内存

    得到这些接收事件的方法之后,遍历这个保存事件方法的List集合,进行subscribe()订阅.

    subscribe源码

    private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
            Class<?> eventType = subscriberMethod.eventType;//记录订阅方法的参数类型
            //newSubscription 记录订阅类和方法
            Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
            CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
            if (subscriptions == null) {
                subscriptions = new CopyOnWriteArrayList<>();
                //以订阅方法参数类型为key,CopyOnWriteArrayList为value
                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<>();
                //订阅的类为 key ,ArrayList 为value
                typesBySubscriber.put(subscriber, subscribedEvents);
            }
            //记录参数类型
            subscribedEvents.add(eventType);
    
            ...
            //sticky粘性事件的一些处理
        }
    

    具体的订阅就是用Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType,一个Map集合,以订阅方法参数类型为key,当前订阅的类的信息,和接收事件的方法信息(方法名字,参数类型,接收线程模式,优先级..等等)为value保存,后面post发送事件的时候,根据参数类型,从上面subscribe订阅时候保存的subscriptionsByEventType集合,获取到对应的类信息和方法,反射调用

    post源码

    public void post(Object event) {
            PostingThreadState postingState = currentPostingThreadState.get();
            List<Object> eventQueue = postingState.eventQueue;
            //把传递的对象添加List集合队列
            eventQueue.add(event);
    
            if (!postingState.isPosting) { //默认是fasle,这里满足
                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;
                }
            }
        }
    

    把post要传递的对象添加eventQueue这个List集合队列里面,然后到while 里面循环遍历,调用postSingleEvent发送事件消息,postSingleEvent方法会调用postSingleEventForEventType方法来完成.

    postSingleEventForEventType

     private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class<?> eventClass) {
            CopyOnWriteArrayList<Subscription> subscriptions;
            synchronized (this) {
                //这里就根据 post要传递的参数类型,获取到对应的类和方法的信息
                subscriptions = subscriptionsByEventType.get(eventClass);
            }
            if (subscriptions != null && !subscriptions.isEmpty()) {
                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;
        }
    

    可以看到,这里是根据要传递的参数类型(EventBus.getDefault().post(传递参数)),来获取到上面订阅的时候保存的类和方法的信息,然后遍历,调用postToSubscription方法,去发送事件消息

    postToSubscription

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

    判断订阅方法的threadMode模式,利用不同线程的Handler进行线程切换,做不同的处理.最后都是调用invokeSubscriber方法通过反射调用到接收事件通知的方法来完成事件的通知过程..

    invokeSubscriber

    void invokeSubscriber(Subscription subscription, Object event) {
            try {
                subscription.subscriberMethod.method.invoke(subscription.subscriber, event);// 反射调用方法
            } catch (InvocationTargetException e) {
                handleSubscriberException(subscription, event, e.getCause());
            } catch (IllegalAccessException e) {
                throw new IllegalStateException("Unexpected exception", e);
            }
        }
    

    unregister注销注册源码

    //订阅的类为 key ,接收事件方法的参数类型的List集合 为value
    //typesBySubscriber.put(subscriber, subscribedEvents);
    
    public synchronized void unregister(Object subscriber) {
            //typesBySubscriber订阅事件的时候,保存的信息
            List<Class<?>> subscribedTypes = typesBySubscriber.get(subscriber);
            if (subscribedTypes != null) {
                for (Class<?> eventType : subscribedTypes) {
                    unsubscribeByEventType(subscriber, eventType);//遍历删除
                }
                typesBySubscriber.remove(subscriber);//从Map集合里面删除
            } else {
                Log.w(TAG, "Subscriber to unregister was not registered before: " + subscriber.getClass());
            }
        }
    

    注销注册就是从对应的Map集合里面把对应的订阅者类,删除掉.

    unsubscribeByEventType

    private void unsubscribeByEventType(Object subscriber, Class<?> eventType) {
            //根据参数类型,获取到对应的订阅者类的集合
            List<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
            if (subscriptions != null) {
                int size = subscriptions.size();
                for (int i = 0; i < size; i++) {   //遍历删除
                    Subscription subscription = subscriptions.get(i);
                    if (subscription.subscriber == subscriber) {
                        subscription.active = false;
                        subscriptions.remove(i);
                        i--;
                        size--;
                    }
                }
            }
        }
    

    相关文章

      网友评论

          本文标题:EventBus3.0源码分析记录

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