Android之EventBus源码分析(一)

前言

今天来学习一下事件总线EventBus的源码流程,对于EventBus,想必同学们都非常熟悉了。那么我们通过分析EventBus的源码,来思考以下几个问题。

  • EventBus用到了哪几种设计模式?
  • EventBus是如何识别订阅者的?
  • EventBus如何注销订阅者呢?

构造方法

 public EventBus() {
        this(DEFAULT_BUILDER);
    }
 EventBus(EventBusBuilder builder) {
        this.currentPostingThreadState = new ThreadLocal<EventBus.PostingThreadState>() {
            protected EventBus.PostingThreadState initialValue() {
                return new EventBus.PostingThreadState();
            }
        };
        this.logger = builder.getLogger();
        this.subscriptionsByEventType = new HashMap();
        this.typesBySubscriber = new HashMap();
        this.stickyEvents = new ConcurrentHashMap();
        this.mainThreadSupport = builder.getMainThreadSupport();
        this.mainThreadPoster = this.mainThreadSupport != null ? this.mainThreadSupport.createPoster(this) : null;
        this.backgroundPoster = new BackgroundPoster(this);
        this.asyncPoster = new AsyncPoster(this);
        this.indexCount = builder.subscriberInfoIndexes != null ? builder.subscriberInfoIndexes.size() : 0;
        this.subscriberMethodFinder = new SubscriberMethodFinder(builder.subscriberInfoIndexes, builder.strictMethodVerification, builder.ignoreGeneratedIndex);
        this.logSubscriberExceptions = builder.logSubscriberExceptions;
        this.logNoSubscriberMessages = builder.logNoSubscriberMessages;
        this.sendSubscriberExceptionEvent = builder.sendSubscriberExceptionEvent;
        this.sendNoSubscriberEvent = builder.sendNoSubscriberEvent;
        this.throwSubscriberException = builder.throwSubscriberException;
        this.eventInheritance = builder.eventInheritance;
        this.executorService = builder.executorService;
    }
复制代码

可以看出EventBus实际上只有一个构造方法,并且从构造方法中我们可以看到许多熟悉的属性。比如mainThreadSupport、mainThreadPoster、backgroundPoster,它们像不像EventBus的几种线程模式?而且从executorService来看,我们可以猜测下EventBus存在自己的线程池。

EventBus.getDefault()

 public static EventBus getDefault() {
        if (defaultInstance == null) {
            Class var0 = EventBus.class;
            synchronized(EventBus.class) {
                if (defaultInstance == null) {
                    defaultInstance = new EventBus();
                }
            }
        }
        return defaultInstance;
    }
复制代码

从源码中我们可以看出,使用了单例模式来获取EventBus实例。

register()

 public void register(Object subscriber) {
 		//subscriber一般是指订阅者,比如Activity
        //这里获取了subscriber的class
        Class<?> subscriberClass = subscriber.getClass();
        //获得了一个具有订阅方法的subscriberMethods集合
        List<SubscriberMethod> subscriberMethods = this.subscriberMethodFinder.findSubscriberMethods(subscriberClass);
        synchronized(this) {
            Iterator var5 = subscriberMethods.iterator();
            while(var5.hasNext()) {
                SubscriberMethod subscriberMethod = (SubscriberMethod)var5.next();
                //开始进行注册
                this.subscribe(subscriber, subscriberMethod);
            }
        }
    }
复制代码

EventBus的注册流程主要分为以下几步:

  • 获取订阅者的class对象
  • 获取订阅者所有的订阅方法
  • 进行注册

findSubscriberMethods()

List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
    	//首先查看缓存中是否存在
        List<SubscriberMethod> subscriberMethods = (List)METHOD_CACHE.get(subscriberClass);
        if (subscriberMethods != null) {
            return subscriberMethods;
        } else {
        	//ignoreGeneratedIndex默认为false,所以我们来看findUsingInfo()方法
            if (this.ignoreGeneratedIndex) {
                subscriberMethods = this.findUsingReflection(subscriberClass);
            } else {
                subscriberMethods = this.findUsingInfo(subscriberClass);
            }

            if (subscriberMethods.isEmpty()) {
                throw new EventBusException("Subscriber " + subscriberClass + " and its super classes have no public methods with the @Subscribe annotation");
            } else {
            	//最后将subscriberClass、subscriberMethods添加到缓存中
                METHOD_CACHE.put(subscriberClass, subscriberMethods);
                return subscriberMethods;
            }
        }
    }
复制代码

findUsingInfo()

 private List<SubscriberMethod> findUsingInfo(Class<?> subscriberClass) {
         //...
            } else {
                this.findUsingReflectionInSingleClass(findState);
            }
        }
        return this.getMethodsAndRelease(findState);
    }
复制代码

我们主要来看findUsingReflectionInSingleClass()方法,源码如下:

private void findUsingReflectionInSingleClass(SubscriberMethodFinder.FindState findState) {
        Method[] methods;
        try {
        	//通过反射获得订阅者所有的方法
            methods = findState.clazz.getDeclaredMethods();
        } catch (Throwable var12) {
            methods = findState.clazz.getMethods();
            findState.skipSuperClasses = true;
        }
   			//...
                if (parameterTypes.length == 1) {
                	//获得了注解
                    Subscribe subscribeAnnotation = (Subscribe)method.getAnnotation(Subscribe.class);
                    if (subscribeAnnotation != null) {
                        Class<?> eventType = parameterTypes[0];
                        if (findState.checkAdd(method, eventType)) {
                        	//获得了ThreadMode属性
                            ThreadMode threadMode = subscribeAnnotation.threadMode();
                         	//最后将method, eventType, threadMode, priority(),sticky这些属性包装成一个SubscriberMethod,并添加到subscriberMethods集合中
                            findState.subscriberMethods.add(new SubscriberMethod(method, eventType, threadMode, subscribeAnnotation.priority(), subscribeAnnotation.sticky()));
                        }
                    }
             //...
复制代码

查找带有注解的订阅方法主要流程有以下几步:

  • 首先查看缓存中是否存在subscriberMethods,如果存在就返回缓存,不存在则进行下一步
  • 通过反射获取订阅者所有的方法
  • 查找带有注解的订阅方法,并将订阅方法相关属性信息包装成SubscriberMethod对象,添加到集合

subscribe()

private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
        Class<?> eventType = subscriberMethod.eventType;
        //将subscriber和subscriberMethod添加到Subscription
        Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
        //将Subscription添加到CopyOnWriteArrayList集合
        CopyOnWriteArrayList<Subscription> subscriptions = (CopyOnWriteArrayList)this.subscriptionsByEventType.get(eventType);
        if (subscriptions == null) {
            subscriptions = new CopyOnWriteArrayList();
            this.subscriptionsByEventType.put(eventType, subscriptions);
        } else if (subscriptions.contains(newSubscription)) {
            throw new EventBusException("Subscriber " + subscriber.getClass() + " already registered to event " + eventType);
        }
		//...

    }
复制代码

在源码中,将订阅者和订阅方法添加到了一个Subscription中,然后又从subscriptionsByEventType集合中获得一个Subscription类型的subscriptions集合。

private final Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType;
复制代码

subscriptionsByEventType是一个key为class,value为CopyOnWriteArrayList集合的Map集合。在subscribe()方法中我们也看到了最终订阅者和订阅方法被添加到了一个subscriptions的CopyOnWriteArrayList集合中,也就是说subscribe()方法主要作用是保存订阅者和订阅方法相关信息,然后在EventBus发出事件时,可以识别已经注册的订阅者。

unregister()

 public synchronized void unregister(Object subscriber) {
        List<Class<?>> subscribedTypes = (List)this.typesBySubscriber.get(subscriber);
        if (subscribedTypes != null) {
            Iterator var3 = subscribedTypes.iterator();
            while(var3.hasNext()) {
                Class<?> eventType = (Class)var3.next();
                this.unsubscribeByEventType(subscriber, eventType);
            }
            this.typesBySubscriber.remove(subscriber);
        } else {
            this.logger.log(Level.WARNING, "Subscriber to unregister was not registered before: " + subscriber.getClass());
        }
复制代码

首先我们来看一下unsubscribeByEventType()方法

private void unsubscribeByEventType(Object subscriber, Class<?> eventType) {
        List<Subscription> subscriptions = (List)this.subscriptionsByEventType.get(eventType);
        if (subscriptions != null) {
            int size = subscriptions.size();

            for(int i = 0; i < size; ++i) {
                Subscription subscription = (Subscription)subscriptions.get(i);
                if (subscription.subscriber == subscriber) {
                    subscription.active = false;
                    subscriptions.remove(i);
                    --i;
                    --size;
                }
            }
        }
复制代码

看到这里,我们是不是明白了unregister()方法?unregister()方法就是删除EventBus中已经注册的订阅者相关信息,与register()方法作用相反。

总结

本篇文章我们分析了EventBus的register()和unregister()方法的源码流程,明白了两个方法的主要作用。了解了EventBus是如何注册订阅者,并识别订阅者的。在下一篇文章中,我们将会分析EventBus是如何分发事件的。

转载于:https://juejin.im/post/5d256437f265da1bac403f1d

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值