Android之EventBus源码浅析

    自EventBus问世后,带给众码农福利多多。不仅简而易用,而且代码简洁明了。虽然Activity之间以及fragment之间的消息通信可以使用很多方式实现,比如广播,接口回调,但是与EventBus相比起来,还是觉得后者更加犀利。 发动机虽好用,可是一旦出了问题一脸懵逼,所以起码也要稍微明白发动力是怎么工作的吧。所以我打开EventBus的源码,开始十目一行的阅读,慢慢的分析,发现了EventBus的奥妙所在.

compile 'org.greenrobot:eventbus:3.0.0' //直接在项目中依赖
//都是声明了Map集合,虽然从这里看不出各个集合的用处,但是大概明白了EventBus是需要这些集合来存储事件的
private static final Map<Class<?>, List<Class<?>>> eventTypesCache = new HashMap<>();
private final Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType;
private final Map<Object, List<Class<?>>> typesBySubscriber;
private final Map<Class<?>, Object> stickyEvents;
//1.首先看了最先使用的register方法
public void register(Object subscriber) {
        Class<?> subscriberClass = subscriber.getClass();//获取注册类的类型
        List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);//获取该类中注册过的所有方法
        synchronized (this) {
            for (SubscriberMethod subscriberMethod : subscriberMethods) {//循环这些方法,并且传递给subscribe方法中
                subscribe(subscriber, subscriberMethod);
            }
        }
    }
 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) {//如果集合为null,新建一个CopyOnWriteArrayList,把这个类型用map保存起来
            subscriptions = new CopyOnWriteArrayList<>();
            subscriptionsByEventType.put(eventType, subscriptions);
        } else {//如果集合不为null,检查一下是否在该类中已经注册了。
            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);//获取用该类作为key对应的value集合
        if (subscribedEvents == null) {//如果没有的话就创建一个
            subscribedEvents = new ArrayList<>();
            typesBySubscriber.put(subscriber, subscribedEvents);
        }
        subscribedEvents.add(eventType);//最后将注册的方法类型保存在这个集合中

    }
//2.然后看了unregister方法是如何实现的
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 {
            Log.w(TAG, "Subscriber to unregister was not registered before: " + subscriber.getClass());
        }
    }
 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--;
                }
            }
        }
    }
//3.最后看了post的使用原理
    public void post(Object event) {
        PostingThreadState postingState = currentPostingThreadState.get();//应该是获取了消息队列
        List<Object> eventQueue = postingState.eventQueue;
        eventQueue.add(event);//把事件加入到消息队列中

        if (!postingState.isPosting) {//判断是否在发送
            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);//取一个去掉一个,然后传递给postSingleEvent方法
                }
            } finally {
                postingState.isPosting = false;
                postingState.isMainThread = false;
            }
        }
    }
private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {
        Class<?> eventClass = event.getClass();
        boolean subscriptionFound = false;
        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) {
            if (logNoSubscriberMessages) {
                Log.d(TAG, "No subscribers registered for event " + eventClass);
            }
            if (sendNoSubscriberEvent && eventClass != NoSubscriberEvent.class &&
                    eventClass != SubscriberExceptionEvent.class) {
                post(new NoSubscriberEvent(this, event));
            }
        }
    }
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);
        }
    }
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);
        }
    }

总结:
1.所有注册的事件类型,都以键值对的方式存储在typesBySubscriber集合中。
2.register实际就是往map中添加注册的对象,unRegister则是从map中去掉注册的对象。
3.如果父类与子类也注册有同样类型的方法,两者都会同时执行。
4.注册的方法被唤起执行是通过反射机制实现的。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值