美文网首页
EventBus3.1.1源码学习

EventBus3.1.1源码学习

作者: 程序狮 | 来源:发表于2018-11-23 17:07 被阅读67次

此文章是建立在已经掌握EventBus的使用方法基础上的,不会的参考官网

我们通过2步来讲解,首先是注册、接收回调与发送消息,然后讲解一下解除注册

第一步:

1、注册类:注册与回调方法

EventBus.getDefault().register(this);

    /**
     * 注解回调的方法
     * @param messageEvent
     */
  @Subscribe(threadMode = ThreadMode.MAIN)
  public void optionEvent(MessageEvent messageEvent){
      textView.setText(messageEvent.getMessage());
  }

此时我们查看一下源码

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

我们知道注册时回调的方法名是可以随便起的,原因就是上面第3句(findSubscriberMethods),有一个方法可以遍历处理此类的所有使用过@Subscribe此注解的方法集合。
接着可以看到,下面是遍历所有需要回调的方法集,调用了subscribe方法,我们来看一下此方法,代码太长我们贴主要代码

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

这里我们看到有一个subscriptionsByEventType成员变量,此变量是以EventType为key,而Value是Subscription集合,我们通过源码可以看到,这里是通过EventType把所有注册类下面相同参数的方法进行了分组。
也就是说注册类下面有几个接收回调的方法,就有几个Subscription类对象,而且同一个类可以写多个相同结果回调方法,方法名可以不同,源码都会先进行分组后放进subscriptionsByEventType集合中。
2、发送消息

MessageEvent messageEvent = new MessageEvent(editText.getText().toString());
EventBus.getDefault().post(messageEvent);

我们看一下源码

private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class<?> eventClass) {
        CopyOnWriteArrayList<Subscription> subscriptions;
        synchronized (this) {
            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;
    }

我们可以看到,这里就是遍历subscriptionsByEventType此集合,通过传入的EventType得到所有注册过以此方法为参数的对象,通过反射调用对象下面的方法。

第二步:取消注册

EventBus.getDefault().unregister(this);

我们看一下源码

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 {
            logger.log(Level.WARNING, "Subscriber to unregister was not registered before: " + subscriber.getClass());
        }
    }

我们可以看到,取消注册是通过遍历typesBySubscriber集合,来把添加到subscriptionsByEventType集合的数值移除掉,然后再从typesBySubscriber移除掉(因为注册传入的是this,所以一定要进行解除注册,否则会造成内存泄漏),我们回头在看一下typesBySubscriber集合,是在注册时集合加入的

List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);
        if (subscribedEvents == null) {
            subscribedEvents = new ArrayList<>();
            typesBySubscriber.put(subscriber, subscribedEvents);
        }
        subscribedEvents.add(eventType);

此集合是以注册类对象为key,EventType为value进行存储,目的就是为了解除注册时方便从subscriptionsByEventType集合中移除注册的方法。

讲到这里,整个EventBus处理的流程是讲完了,这次是第一次完整的自己分析源码,讲一下感受:
当我们要研究一个项目的源码时,开始一定要先会使用此项目,然后通过使用的入口,进行Debug查看调用流程,然后看源码的时候刚开始不要太细钻研每个调用方法是干什么用的,要先理清整个脉络,然后再回头单块攻克主要的成员变量是干什么用的,为什么这么用,如果理不清楚,可以用笔写一下,每个值是干什么用的,真的很有用!!
最后贴一下我梳理时的笔记,字有点丑介意的话,请....你懂得


eventBus总结.jpg

相关文章

网友评论

      本文标题:EventBus3.1.1源码学习

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