美文网首页工作生活
Android EventBus 源码解析

Android EventBus 源码解析

作者: 南风向北zhy | 来源:发表于2019-07-01 17:26 被阅读0次

对于EventBus 想必作为安卓开发都不会陌生,这边也不会进行讲解使用方法,只是本人在准备面试重新又撸了一遍源码,回味而已,希望给各位看官意犹未尽的感觉。

原理图在此
EventBus-Publish-Subscribe.png
带问题查看源码

当前看源码的时候肯定是带着问题看才能不会适可而止,所以我的问题如下:
1.register(),unregister()如何绑定?
2.@Subscribe 注解之后是不是用反射找到对应的方法?指定 theardMode 如何实现线程切换?
3.如何发送事件.粘性事件?
总结就是:如何绑定对应的事件,如果发送与接受事件

看源码如何入手

EventBus 查看源码相对于RxJava,Retrofit还是比较容易的,入口很明显

  @Override
    protected void onStart() {
        super.onStart();
        EventBus.getDefault().register(this);//绑定生命周期
    }
    @Override
    protected void onStop() {
        super.onStop();
        EventBus.getDefault().register(this);//绑定生命周期
    }

 EventBus.getDefault().post(new MessageEvent("test"));

 @Subscribe(threadMode = ThreadMode.MAIN)
    public void testEventBus(Message message){
        System.out.println(message.msg);
    }
1. EventBus.getDefault() 获取实例 EventBus.class

//获取静态的单例的实例对象
static volatile EventBus defaultInstance;

    public static EventBus getDefault() {
        if (defaultInstance == null) {
            synchronized (EventBus.class) {
                if (defaultInstance == null) {
                    defaultInstance = new EventBus();
                }
            }
        }
        return defaultInstance;
    }

这种单例好像是非常流行的写法:volatile 关键字声明 以及进行双重效验有啥好处?我的理解:

  • 第一个if判断可以在多个线程进入方法的时候过滤掉不为Null的线程,直接返回单实例。
  • 为空的线程到第二个线程由于同步锁的原因只能进行一次初始化,相当于只能由一个线程进入锁中进行实例化对象。有点hashCode() 和 equal() 的味道。
//单例为什么是public ,我认为每个线程都能注册得到相应的EventBus事件总线,都是相互隔离的
  public EventBus() {
       this(DEFAULT_BUILDER);// EventBusBuilder  构建者模式
   }
private static final EventBusBuilder DEFAULT_BUILDER = new EventBusBuilder(); //EventBusBuilder  构建者模式
//初始化 下面过滤了比较重要的内容,先有一个大概印象,我都是看到后面才发现这些东西的重要性
 EventBus(EventBusBuilder builder) {
       ...
       subscriptionsByEventType = new HashMap<>(); //通过存储的key(class)找到订阅者
       typesBySubscriber = new HashMap<>();//注册之后会操作这个Map
       stickyEvents = new ConcurrentHashMap<>();//粘性事件
     
       mainThreadPoster = mainThreadSupport != null ? mainThreadSupport.createPoster(this) : null; //一个Handler
       backgroundPoster = new BackgroundPoster(this); //一个线程
       asyncPoster = new AsyncPoster(this); //一个线程

       subscriberMethodFinder = new SubscriberMethodFinder(builder.subscriberInfoIndexes,
               builder.strictMethodVerification, builder.ignoreGeneratedIndex); //@Subscriber注解方法找寻器

  executorService = builder.executorService;//线程池
       ...
   }
2.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);
            }
        }
    }

subscriberMethodFinder.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); //执行此处找到相应的subscriberMethods 进行添加与返回
        }
        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;
        }
    }

findUsingInfo 保存注解过的方法和状态

   private List<SubscriberMethod> findUsingInfo(Class<?> subscriberClass) {
        FindState findState = prepareFindState();//prepareFindState 查找遍历旧的集合是否存在,不存在就创建新的FindState  ,FindState 封装了集合进行保存相应的 class 与 method
        findState.initForSubscriber(subscriberClass);
        while (findState.clazz != null) {
            findState.subscriberInfo = getSubscriberInfo(findState);
            if (findState.subscriberInfo != null) {
                SubscriberMethod[] array = findState.subscriberInfo.getSubscriberMethods();
                for (SubscriberMethod subscriberMethod : array) {
                    if (findState.checkAdd(subscriberMethod.method, subscriberMethod.eventType)) {//
                        findState.subscriberMethods.add(subscriberMethod);
                    }
                }
            } else {
                findUsingReflectionInSingleClass(findState); //通过反射 获取class 被注解的方法@Subscriber 然后添加到findState.subscriberMethods.add()
            }
            findState.moveToSuperclass();
        }
        return getMethodsAndRelease(findState); //返回与findState 资源释放
    }

每个方法的订阅 subscribe()


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

subscribe 代码有点长,简要概述一下:通过判断subscriptionsByEventType typesBySubscriber 两个集合是否存在进行相应的操作,最后判断是否是粘性事件进行 checkPostStickyEventToSubscription

☆☆☆☆☆ 重点来了,事件分发 checkPostStickyEventToSubscription 调用 postToSubscription(newSubscription, stickyEvent, isMainThread());

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); 通过HandlerPoster 添加到队列中
                }
                break;
            case MAIN_ORDERED:
                if (mainThreadPoster != null) {
                    mainThreadPoster.enqueue(subscription, event);
                } else {
                    // temporary: technically not correct as poster not decoupled from subscriber
                    invokeSubscriber(subscription, event);
                }
                break;
            case BACKGROUND: 
                if (isMainThread) {
                    backgroundPoster.enqueue(subscription, event);  //BackgroundPoster 遍历PendingPost中 pendingPostPool 集合里面的事件,每个事件都执行
                } else {
                    invokeSubscriber(subscription, event);
                }
                break;
            case ASYNC: 
                asyncPoster.enqueue(subscription, event);//AsyncPoster  PendingPost中 pendingPostPool 集合里面的一个事件并执行。
                break;
            default:
                throw new IllegalStateException("Unknown thread mode: " + subscription.subscriberMethod.threadMode);
        }
    }
post()
   private final ThreadLocal<PostingThreadState> currentPostingThreadState = new ThreadLocal<PostingThreadState>() {
        @Override
        protected PostingThreadState initialValue() {
            return new PostingThreadState();
        }
    };

   public void post(Object event) {
        PostingThreadState postingState = currentPostingThreadState.get(); // ThreadLocal 是不会让其他线程共享的,线程独有的
        List<Object> eventQueue = postingState.eventQueue;
        eventQueue.add(event);

        if (!postingState.isPosting) {//是否正在发送
            postingState.isMainThread = isMainThread();//是否在主线程中
            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;
            }
        }
    }

postSingleEvent

    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);//找到订阅的方法 遍历之前register 中 集合 subscriptionsByEventType (存着可以为class ,value 为mothod),进行遍历postToSubscription 
        }
        if (!subscriptionFound) {
            if (logNoSubscriberMessages) {
                logger.log(Level.FINE, "No subscribers registered for event " + eventClass);
            }
            if (sendNoSubscriberEvent && eventClass != NoSubscriberEvent.class &&
                    eventClass != SubscriberExceptionEvent.class) {
                post(new NoSubscriberEvent(this, event)); //
            }
        }
    }

至此:EventBus 的基本事件完结,由于篇幅过程,Sticky后续讲解

总结:EventBus

1.EventBus 通过双重效验进行返回单实例对象,通过EventBusBuilder 构造者模式进行初始化一些重要参数,例如以下 Poster,SubscriberMethodFinder方法查询器,存放方法注解的集合subscriptionsByEventType等,值得注意的是一些封装类 SubscriberMethod,FindState
2.register 把保存在集合中的所有事件进行订阅 放到相应的队列中
3.post方法进行从队列中获取,通过handler进行事件的发送

本人水平有限,如有不对的地方,欢迎指正,共同进步

相关文章

网友评论

    本文标题:Android EventBus 源码解析

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