探究EventBus的运行原理

1 EventBus简介

EventBus是由greenrobot组织贡献的一个Android事件发布/订阅轻量级框架。它的github地址是:
https://github.com/greenrobot/EventBus

看看github上面的简(吹)介(捧):

EventBus...
simplifies the communication between components
decouples event senders and receivers
performs well with Activities, Fragments, and background threads
avoids complex and error-prone dependencies and life cycle issues
makes your code simpler
is fast
is tiny (~60k jar)
is proven in practice by apps with 1,000,000,000+ installs
has advanced features like delivery threads, subscriber priorities, etc.

EventBus简化了应用程序内各个组件之间进行通信的复杂度,尤其是碎片之间进行通信的问题,可以避免由于使用广播通信而带来的诸多不便。而且它很快,包只有60k已经安装在了1,000,000,000+个应用中广泛使用了。

2 EventBus的简单使用

1 gradle中添加依赖

implementation 'org.greenrobot:eventbus:3.2.0'

火星瓢虫_001.png

2 添加混淆到混淆文件中。
*-keepattributes Annotation
-keepclassmembers class * {
@org.greenrobot.eventbus.Subscribe ;
}
-keep enum org.greenrobot.eventbus.ThreadMode { *; }

如果你有用到AsyncExecutor类
-keepclassmembers class * extends org.greenrobot.eventbus.util.ThrowableFailureEvent {
(java.lang.Throwable);
}*

3 开始使用:
定义一个事件:

public  class MessageEvent {
    /* Additional fields if needed */
    public String message;

    public MessageEvent(String message) {
        this.message = message;
    }
 
}

准备订阅者的事件接收方法:

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onMessageEvent(MessageEvent event) {
        Toast.makeText(this,event.message,Toast.LENGTH_LONG).show();
    }

注册和解除订阅者的订阅事件:

  @Override
    protected void onStart() {
        super.onStart();
        EventBus.getDefault().register(this);
    }

    @Override
    protected void onStop() {
        super.onStop();
        EventBus.getDefault().unregister(this);
    }

发送事件:

findViewById(R.id.hello_eventBus).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                EventBus.getDefault().post(new MessageEvent("this is  an event"));
            }
        });

现在我们点击hello_eventBus这个控件,就是弹出Toast对话框。接下来一步步分析EventBus是如何实现这样的工作的:

先看一下EventBus.getDefault().register(this);这个方法;

3. EventBus的初始化

进入EventBus类中:

 //使用单例模式构造EventBus  
    public static EventBus getDefault() {
        EventBus instance = defaultInstance;
        if (instance == null) {
            synchronized (EventBus.class) {
                instance = EventBus.defaultInstance;
                if (instance == null) {
                    instance = EventBus.defaultInstance = new EventBus();
                }
            }
        }
        return instance;
    }
   // 建造者模式
    private static final EventBusBuilder DEFAULT_BUILDER = new EventBusBuilder();

    public EventBus() {
        this(DEFAULT_BUILDER);
    }

    //初始化EventBus内部的一些组件 
    EventBus(EventBusBuilder builder) {

        logger = builder.getLogger();
        // Event为key,Subscription为Value的发布者
        subscriptionsByEventType = new HashMap<>();
        //Subscriber为key,Event为Value
        typesBySubscriber = new HashMap<>();
        //维护的粘性事件
        stickyEvents = new ConcurrentHashMap<>();
        // 提供主线程的相关组件支持
        mainThreadSupport = builder.getMainThreadSupport();
        // 重点分析内容
        mainThreadPoster = mainThreadSupport != null ? mainThreadSupport.createPoster(this) : null;
        backgroundPoster = new BackgroundPoster(this);
        asyncPoster = new AsyncPoster(this);
        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;
        //没有事件处理 是否发送      NoSubscriberEvent事件  
        sendNoSubscriberEvent = builder.sendNoSubscriberEvent;
        //是否抛出异常      
        throwSubscriberException = builder.throwSubscriberException;
        eventInheritance = builder.eventInheritance;
        executorService = builder.executorService;
    }

可以看到EventBus使用了单例模式创建,同时使用了构建者模式创建了一些必要的组件集合。

    // key 为 Class 对象,value 为被订阅者的集合 
    private final Map, CopyOnWriteArrayList> subscriptionsByEventType;
    // key 为 Object 对象,value 为订阅者的集合 
    private final Map>> typesBySubscriber;
   // key 为 Class 对象,value 为 Object 对象
    private final Map, Object> stickyEvents;

上述几个集合先简单进行描述;

接下来先重点关注到几个相关的 Poster 是做什么?

MainThreadSupport

mainThreadSupport = builder.getMainThreadSupport();

  // 获取looper
  MainThreadSupport getMainThreadSupport() {
        if (mainThreadSupport != null) {
            return mainThreadSupport;
        } else if (AndroidLogger.isAndroidLogAvailable()) {
            Object looperOrNull = getAndroidMainLooperOrNull();
            return looperOrNull == null ? null :
                    new MainThreadSupport.AndroidHandlerMainThreadSupport((Looper) looperOrNull);
        } else {
            return null;
        }
    }

   static Object getAndroidMainLooperOrNull() {
        try {
            return Looper.getMainLooper();// 获取主线程的 Looper
        } catch (RuntimeException e) {
            // Not really a functional Android (e.g. "Stub!" maven dependencies)
            return null;
        }
    }

public interface MainThreadSupport {

    boolean isMainThread();

    Poster createPoster(EventBus eventBus);

    class AndroidHandlerMainThreadSupport implements MainThreadSupport {

        private final Looper looper;

        public AndroidHandlerMainThreadSupport(Looper looper) {
            this.looper = looper;
        }

        @Override
        public boolean isMainThread() {
            return looper == Looper.myLooper();
        }

        @Override
        public Poster createPoster(EventBus eventBus) {
            return new HandlerPoster(eventBus, looper, 10);
        }
    }

}

可以看到 MainThreadSupport 主要获取的是主线程的 Looper(通过 Looper.getMainLooper() 方法),AndroidHandlerMainThreadSupport 顾名思义,也是想要支持一些主线程将要进行的操作;

继续查看 createPoster 方法 创建了一个 HandlerPoster 的实例;

public class HandlerPoster extends Handler implements Poster {
    private final PendingPostQueue queue;  //PendingPostQueue 队列
    private final int maxMillisInsideHandleMessage;
    private final EventBus eventBus;
    private boolean handlerActive;

    protected HandlerPoster(EventBus eventBus, Looper looper, int maxMillisInsideHandleMessage) {
        super(looper);
        this.eventBus = eventBus;
        this.maxMillisInsideHandleMessage = maxMillisInsideHandleMessage;
        queue = new PendingPostQueue();
    }
    // 接收到了发送的消息
    public void enqueue(Subscription subscription, Object event) {
     
    }
    //处理消息
    @Override
    public void handleMessage(Message msg) {
     
}

HandlerPoster 类实现了 Handler 类,这里肯定和消息的处理有关,即实例中对应的 Toast 响应;

这里先对 enqueue 方法进行分析;

    public void enqueue(Subscription subscription, Object event) {
        PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
        synchronized (this) {
            queue.enqueue(pendingPost);
            if (!handlerActive) {// 如果未处理
                handlerActive = true;
                if (!sendMessage(obtainMessage())) {// 发送消息
                    throw new EventBusException("Could not send handler message");
                }
            }
        }
    }

了解 enqueue 方法之前,看来得先看看 PendingPost 是干嘛的;

PendingPost

final class PendingPost {
    private final static List pendingPostPool = new ArrayList();//PendingPost 池

    Object event;
    Subscription subscription;
    PendingPost next;

    private PendingPost(Object event, Subscription subscription) {
        this.event = event;
        this.subscription = subscription;
    }
   
    // 相当于组装一个 PendingPost 对象返回
    static PendingPost obtainPendingPost(Subscription subscription, Object event) {
        synchronized (pendingPostPool) {
            int size = pendingPostPool.size();
            if (size > 0) {
                PendingPost pendingPost = pendingPostPool.remove(size - 1);
                pendingPost.event = event;
                pendingPost.subscription = subscription;
                pendingPost.next = null;
                return pendingPost;
            }
        }
        return new PendingPost(event, subscription);
    }
  
   // 重置 pendingPost 数据 加入到池子中
    static void releasePendingPost(PendingPost pendingPost) {
        pendingPost.event = null;
        pendingPost.subscription = null;
        pendingPost.next = null;
        synchronized (pendingPostPool) {
            // Don't let the pool grow indefinitely
            if (pendingPostPool.size() < 10000) {
                pendingPostPool.add(pendingPost);
            }
        }
    }

}

可以看到 PendingPost 类维护了一个 PendingPost 的池子,每次调用 obtainPendingPost 其实就是组装一个 PendingPost 数据进行返回;

拿到了 PendingPost 之后,enqueue 方法会继续调用 queue.enqueue(pendingPost),这里就要继续查看 PendingPostQueue 类;

PendingPostQueue

final class PendingPostQueue {
    private PendingPost head;
    private PendingPost tail;
    
    synchronized void enqueue(PendingPost pendingPost) { // 添加PendingPost
        if (pendingPost == null) {
            throw new NullPointerException("null cannot be enqueued");
        }
        if (tail != null) { // 添加到最后一位
            tail.next = pendingPost;
            tail = pendingPost;
        } else if (head == null) {
            head = tail = pendingPost;
        } else {
            throw new IllegalStateException("Head present, but no tail");
        }
        notifyAll();
    }


    synchronized PendingPost poll() {// 取 PendingPost 
        PendingPost pendingPost = head;
        if (head != null) {
            head = head.next;
            if (head == null) {
                tail = null;
            }
        }
        return pendingPost;
    }

    synchronized PendingPost poll(int maxMillisToWait) throws InterruptedException {//
        if (head == null) {
            wait(maxMillisToWait);
        }
        return poll();
    }

}

PendingPostQueue 维护了一个 PendingPost 队列,用来添加以及取 PendingPost;PendingPost 添加完成了之后,调用 sendMessage 发送消息;

sendMessage 已经将消息发送出去,接下来继续看 HandlerPoster 的 handlerMessage 方法;

    @Override
    public void handleMessage(Message msg) {
        boolean rescheduled = false;
        try {
            long started = SystemClock.uptimeMillis();
            while (true) {
                PendingPost pendingPost = queue.poll();// 获取到消息
                if (pendingPost == null) {
                    synchronized (this) {
                        // Check again, this time in synchronized
                        pendingPost = queue.poll();// 取出 PendingPost
                        if (pendingPost == null) {
                            handlerActive = false;
                            return;
                        }
                    }
                }
                eventBus.invokeSubscriber(pendingPost); // 调用  invokeSubscriber 处理事件
                long timeInMethod = SystemClock.uptimeMillis() - started;
                if (timeInMethod >= maxMillisInsideHandleMessage) {
                    if (!sendMessage(obtainMessage())) {
                        throw new EventBusException("Could not send handler message");
                    }
                    rescheduled = true;
                    return;
                }
            }
        } finally {
            handlerActive = rescheduled;
        }
    }

到这里,就可以发现了,其实 HandlerPoster 只是利用了 Handler ,当收到消息时候,组装PendingPost,并放入队列中,同时 Handler 发送一个消息,当 Handler 收到消息,则会从队列中取出 PendingPost ,然后最终通过 eventBus.invokeSubscriber(pendingPost) 调用处理事件;

到这里 MainThreadSupport 类介绍完毕,其中涉及到 HandlerPoster、PendingPost、PendingPostQuene 之间的相关操作,简单用以下示意图进行描述:

MainThreadSupport.png

BackgroundPoster

接下来,继续查看 BackgroundPoster 类

final class BackgroundPoster implements Runnable, Poster {

    private final PendingPostQueue queue;
    private final EventBus eventBus;

    private volatile boolean executorRunning;

    BackgroundPoster(EventBus eventBus) {
        this.eventBus = eventBus;
        queue = new PendingPostQueue();
    }
    
    public void enqueue(Subscription subscription, Object event) {// 添加事件
        PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
        synchronized (this) {
            queue.enqueue(pendingPost);
            if (!executorRunning) {
                executorRunning = true;
                eventBus.getExecutorService().execute(this);// 开启线程池执行 run 方法;
            }
        }
    }
  // 从队列取出事件去执行
    @Override
    public void run() {
        try {
            try {
                while (true) {
                    PendingPost pendingPost = queue.poll(1000);// 等待1000ms 去取PendingPost
                    if (pendingPost == null) {
                        synchronized (this) { // 保证同步性,所以下面再次调用 poll 方法确认
                            // Check again, this time in synchronized
                            pendingPost = queue.poll();
                            if (pendingPost == null) { // 没有数据了 返回
                                executorRunning = false;
                                return;
                            }
                        }
                    }
                    eventBus.invokeSubscriber(pendingPost);
                }
            } catch (InterruptedException e) {
                eventBus.getLogger().log(Level.WARNING, Thread.currentThread().getName() + " was interruppted", e);
            }
        } finally {
            executorRunning = false;
        }
    }

}

BackgroundPoster 中 PendingPost 的构造过程与 HandlerPost 一致,与 MainThreadSupport 的 HandlerPoster 不同的是 ,BackgroundPoster 实现了 Runnale 方法;BackgroundPoster 对事件的分发调用处理应该是在 run 的方法中;

BackgroundPoster 构造完成了 PendingPost 后,通过线程池来执行 Runnale ,而 最后处理事件则是通过调用 EventBus 的 invokeSubscriber 方法;

所以 HandlerPoster 主要应用了 Handler 的机制在主线程处理,而 BackgroundPoster 则是直接在子线程取 PendingPost 进行 invokeSubscriber 调用处理;

同样,对 BackgroundPoster 进行示意图简单描述;

BackgroundPoster.png

AsyncPoster

同理 asyncPoster = new AsyncPoster(this):

class AsyncPoster implements Runnable, Poster {

    private final PendingPostQueue queue;
    private final EventBus eventBus;

    AsyncPoster(EventBus eventBus) {
        this.eventBus = eventBus;
        queue = new PendingPostQueue();
    }

    public void enqueue(Subscription subscription, Object event) {
        PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
        queue.enqueue(pendingPost);
        eventBus.getExecutorService().execute(this);
    }

    @Override
    public void run() {
        PendingPost pendingPost = queue.poll();
        if(pendingPost == null) {
            throw new IllegalStateException("No pending post available");
        }
        eventBus.invokeSubscriber(pendingPost);
    }

}

AsyncPoster 和 BackgroundPoster 基本一致,区别在于 AsyncPoster 每次线程池只会取出一条 PendingPost 进行处理;

到这里 MainThreadSupport 中的 HandlerPoster 、BackgroundPoster、AsyncPoster 已经分析完成;

通过分析,以上三个 Poster 主要用于接收到消息信息后的 PendingPost 组装,区别在与主线程去处理消息则需要通过 Handler 机制,而对于子线程,直接开启线程在 run 方法进行处理即可;

接下来我们继续看下进行注解的方法:

    @Subscribe(threadMode = ThreadMode.MAIN,sticky = true)
    public void onMessageEvent(MessageEvent event) {
        Toast.makeText(this,event.message,Toast.LENGTH_LONG).show();
    }

View层进行注解

@Documented
@Retention(RetentionPolicy.RUNTIME) // 运行期间有效
@Target({ElementType.METHOD}) // 方法注解
public @interface Subscribe {
    // 处理事件的所在线程
    ThreadMode threadMode() default ThreadMode.POSTING;
    
    // 是否是粘性事件,
    boolean sticky() default false;

    //时间的优先级
    int priority() default 0;
}

Subscribe 注解方法定义了时间响应的线程、是否为粘性事件、以及事件的优先级。后面发送事件过程会继续进行详细分析;

几种处理事件的线程方式:

public enum ThreadMode {

    POSTING, // 发送event事件的线程进行处理

    MAIN, // 主线程处理,会阻塞 需要防止阻塞主线程

    MAIN_ORDERED,// 主线程处理,不会在主线程阻塞

    BACKGROUND, // 会在后台线程处理事件

    ASYNC // 会创建一个新的线程处理
}

可以看到这里注解主要定义了运行区间以及处理事件的线程,这里的线程和之前分析的HandlerPoster、BackgroundPoster、AsyncPoster 对应;

4 register 注册事件订阅

EventBus.getDefault().register(this);

查看register()方法:

 public void register(Object subscriber) {
        Class subscriberClass = subscriber.getClass(); // 获取注册所在的类
        
        List subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);// 获取订阅的方法
        synchronized (this) {
            for (SubscriberMethod subscriberMethod : subscriberMethods) { // 便利循环去订阅方法
                subscribe(subscriber, subscriberMethod);// 绑定注册类以及订阅方法
            }
        }
    }

register 方法会找到注册所在类(例如BaseActivity),通过 subscriberClass 找到所有的注册方法;通过subscribe 进行绑定;

查看 findSubscriberMethods 方法;

private static final Map, List> METHOD_CACHE = new ConcurrentHashMap<>();

  List findSubscriberMethods(Class subscriberClass) {
       
        List 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;
        }
    }

如果缓存中有则去缓存中取出数据,如果没有,会通过 findUsingInfo 方法去查找类中的订阅方法,继续查看 findUsingInfo 方法:

 private List findUsingInfo(Class subscriberClass) {
        FindState findState = prepareFindState();  // FindState 对象获取
        findState.initForSubscriber(subscriberClass); // 赋值Class
        while (findState.clazz != null) {
            findState.subscriberInfo = getSubscriberInfo(findState); // 获取subscriberInfo 
            if (findState.subscriberInfo != null) {
                SubscriberMethod[] array = findState.subscriberInfo.getSubscriberMethods();  // 获取方法集合
                for (SubscriberMethod subscriberMethod : array) {
                    if (findState.checkAdd(subscriberMethod.method, subscriberMethod.eventType)) {            // 检查方法 
                              findState.subscriberMethods.add(subscriberMethod);  // 添加方法到findState
                    }
                }
            } else { // 获取 SubscriberInfo
                findUsingReflectionInSingleClass(findState);
            }
            findState.moveToSuperclass(); // 去父类查找
        }
       
        return getMethodsAndRelease(findState); // 释放相关资源
    }

findUsingInfo 查找订阅方法主要通过 FindState 类进行操作;

FindState

查看 FindState 类

   static class FindState {
        final List subscriberMethods = new ArrayList<>();  // 订阅的方法集合
        final Map anyMethodByEventType = new HashMap<>(); // EventType事件对应的方法的HashMap集合
        final Map subscriberClassByMethodKey = new HashMap<>();   // methodKey对应的class的HashMap集合
        final StringBuilder methodKeyBuilder = new StringBuilder(128);

        Class subscriberClass;// 注册方法所在的类 class
        Class clazz;
        boolean skipSuperClasses;
        SubscriberInfo subscriberInfo;

        void initForSubscriber(Class subscriberClass) {// 初始化 subscriberClass
            this.subscriberClass = clazz = subscriberClass;
            skipSuperClasses = false;
            subscriberInfo = null;
        }

FindState 主要保存了注册的类Class,以及相关订阅方法信息;

下图所示 FindState 和 SubscriberMethod 的关联;

SubscriberMethod.png

继续往下查看 getSubscriberInfo 方法 ;

    private SubscriberInfo getSubscriberInfo(FindState findState) {
        if (findState.subscriberInfo != null && findState.subscriberInfo.getSuperSubscriberInfo() != null) {
            SubscriberInfo superclassInfo = findState.subscriberInfo.getSuperSubscriberInfo();
            if (findState.clazz == superclassInfo.getSubscriberClass()) {
                return superclassInfo;
            }
        }
        if (subscriberInfoIndexes != null) {
            for (SubscriberInfoIndex index : subscriberInfoIndexes) {
                SubscriberInfo info = index.getSubscriberInfo(findState.clazz);
                if (info != null) {
                    return info;
                }
            }
        }
        return null;
    }

FindState 在初始化完成的时候并没有 SubscriberInfo 信息,实际这里执行了 findUsingReflectionInSingleClass 去获取的;

在这之前还是先看看 SubscriberInfo 类都有什么信息:

public interface SubscriberInfo {
    Class getSubscriberClass();

    SubscriberMethod[] getSubscriberMethods();

    SubscriberInfo getSuperSubscriberInfo();

    boolean shouldCheckSuperclass();
}

是一个接口,那么后面肯定有实现 SubscriberInfo 的类,继续看 findUsingReflectionInSingleClass 方法;

    private void findUsingReflectionInSingleClass(FindState findState) {
        Method[] methods;
        try {
            // This is faster than getMethods, especially when subscribers are fat classes like Activities
            methods = findState.clazz.getDeclaredMethods();// 获取注册类中的所有方法
        } catch (Throwable th) {
            // Workaround for java.lang.NoClassDefFoundError, see https://github.com/greenrobot/EventBus/issues/149
            try {
                methods = findState.clazz.getMethods();// 获取注册类中的所有方法
            } catch (LinkageError error) { // super class of NoClassDefFoundError to be a bit more broad...
                String msg = "Could not inspect methods of " + findState.clazz.getName();
                if (ignoreGeneratedIndex) {
                    msg += ". Please consider using EventBus annotation processor to avoid reflection.";
                } else {
                    msg += ". Please make this class visible to EventBus annotation processor to avoid reflection.";
                }
                throw new EventBusException(msg, error);
            }
            findState.skipSuperClasses = true;
        }
        for (Method method : methods) { // 遍历方法
            int modifiers = method.getModifiers();
            if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) { // public 方法
                Class[] parameterTypes = method.getParameterTypes();
                if (parameterTypes.length == 1) {
                    Subscribe subscribeAnnotation = method.getAnnotation(Subscribe.class);// 获取注解的方法
                    if (subscribeAnnotation != null) {
                        Class eventType = parameterTypes[0];// 注解方法的传参
                        if (findState.checkAdd(method, eventType)) {// 
                            ThreadMode threadMode = subscribeAnnotation.threadMode();// 获取注解方法的线程声明
                            findState.subscriberMethods.add(new SubscriberMethod(method, eventType, threadMode,
                                    subscribeAnnotation.priority(), subscribeAnnotation.sticky()));// 添加到 FindState 中,包含传参,处理事件的线程,优先级,是否是粘性事件
                        }
                    }
                } else if (strictMethodVerification && method.isAnnotationPresent(Subscribe.class)) {
                    String methodName = method.getDeclaringClass().getName() + "." + method.getName();
                    throw new EventBusException("@Subscribe method " + methodName +
                            "must have exactly 1 parameter but has " + parameterTypes.length);
                }
            } else if (strictMethodVerification && method.isAnnotationPresent(Subscribe.class)) {
                String methodName = method.getDeclaringClass().getName() + "." + method.getName();
                throw new EventBusException(methodName +
                        " is a illegal @Subscribe method: must be public, non-static, and non-abstract");
            }
        }
    }

findUsingReflectionInSingleClass 方法通过反射会找到注册类中所有的 subscribe 方法,然后将相关信息构造成 SubscriberMethod 类存到 FindState 的 subscriberMethods 中;

当前注册类 class 中执行完成后,会继续转移到注册类的父类中重复操作。找到父类中所有的订阅方法;直到没有父类了,最后将查找到的 subscriberMethods 返回,并释放 FindState 资源;

以上为默认 FindState.subscriberInfo 为空的情况的逻辑,实则当 subscriberInfo 不为空的情况下,有个 checkAdd 方法也会去查找父类,最终添加 subscriberMethod ;

拿到了所有的 subscriberMethods 方法,接下来则会调用到 subscribe(subscriber, subscriberMethod) 对获取的方法进行绑定:


    private final Map, CopyOnWriteArrayList> subscriptionsByEventType;
    private final Map>> typesBySubscriber;
    private final Map, Object> stickyEvents;
   
    private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
        Class eventType = subscriberMethod.eventType; // 获取事件类型 例如 MessageEvent
        Subscription newSubscription = new Subscription(subscriber, subscriberMethod);//通过subscriber(例如:activity)和 subscriberMethod 组装Subscription对象
        CopyOnWriteArrayList subscriptions = subscriptionsByEventType.get(eventType);   // key:EventType  value:subscriptions查找subscriptions
        if (subscriptions == null) { // 为空新建并加入subscriptions,
            subscriptions = new CopyOnWriteArrayList<>();
            subscriptionsByEventType.put(eventType, subscriptions); // 按照 eventType 分类(example MessageEvent)
        } else {
            if (subscriptions.contains(newSubscription)) { // 不为空且已经有该newSubscription报错
                throw new EventBusException("Subscriber " + subscriber.getClass() + " already registered to event "
                        + eventType);
            }
        }

        // 循环遍历 按照优先级加入到subscriptions列表中
        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;
            }
        }

        // key :subscriber(例如:activity) value:eventType(例如:MessageEvent) 进行添加数据
        List> subscribedEvents = typesBySubscriber.get(subscriber);
        if (subscribedEvents == null) {
            subscribedEvents = new ArrayList<>();
            typesBySubscriber.put(subscriber, subscribedEvents); // 按照 subscriber 分类(example : BaseActivity)
        }
        subscribedEvents.add(eventType);


        
        if (subscriberMethod.sticky) {// 粘性事件会直接去执行相关响应
            if (eventInheritance) { // EventType 的父类 ,实现类的对应 方法同样会被调用
                // Existing sticky events of all subclasses of eventType have to be considered.
                // Note: Iterating over all events may be inefficient with lots of sticky events,
                // thus data structure should be changed to allow a more efficient lookup
                // (e.g. an additional map storing sub classes of super classes: Class -> List).
                Set, Object>> entries = stickyEvents.entrySet();
                for (Map.Entry, Object> entry : entries) {
                    Class candidateEventType = entry.getKey();
                    if (eventType.isAssignableFrom(candidateEventType)) {// 查找父类,实现类对应的EventType 进行调用执行
                        Object stickyEvent = entry.getValue();
                        checkPostStickyEventToSubscription(newSubscription, stickyEvent);
                    }
                }
            } else { // 只会调用这一个事件 马上被调用执行
                Object stickyEvent = stickyEvents.get(eventType);
                checkPostStickyEventToSubscription(newSubscription, stickyEvent);
            }
        }
    }

根据 类中注册的方法,subscribe 方法会根据 EventType 以及 subscriber 注册所在类进行分类;用 Map 结构进行保存数据;

粘性事件会通过 checkPostStickyEventToSubscription 方法马上进行发送;同时根据 eventInheritance 判断是否调用 EventType 对应的父类 以及 实现类的响应方法;

如下述方法中 A、B、C事件对应方法均会执行;

public class MainActivity extends Activity {
    private static final String TAG="EventBus";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
    @Override
    protected void onStart() {
        super.onStart();
        Log.v(TAG, "onStart()");
        EventBus.getDefault().register(this);
        EventBus.getDefault().post(new A());
    }
    @Override
    protected void onStop() {
        super.onStop();
        EventBus.getDefault().unregister(this);
        Log.v(TAG, "onStop()");
    }
    public void onEvent(A msg){
        Log.v(TAG, "onEvent(A msg)");
    }
    public void onEvent(B msg){
        Log.v(TAG,"onEvent(B msg)");
    }
    public void onEvent(C msg){
        Log.v(TAG,"onEvent(C msg)");
    }
    public void onEvent(D msg){
        Log.v(TAG,"onEvent(D msg)");
    }
}

到此,总结 EventBus.getDefalut().register(this) 方法主要做了以下工作:
1、创建HandlerPoster、BackgroundPoster、AsyncPoster去对应处理发送的消息;
2、获取注册类中的 subscriberMethod 方法,并且按照分类对应存储在 Map 中;
3、获取粘性事件,直接进行发送处理事件;

在上述 subscribe 方法中,粘性事件的处理方法 checkPostStickyEventToSubscription 还未进行查看,这里先放着,待后续分析发送事件后一起查看;

接下来继续看发送事件的方法

5 事件的返送

EventBus.getDefault().post(new MessageEvent("this is an event"));

    public void post(Object event) {
        PostingThreadState postingState = currentPostingThreadState.get();
        List 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;
            }
        }
    }

 
 

可以看到的是 eventQueue 维护了事件队列,并从 eventQueue 中取事件进行发送;

eventQueue 由 PostingThreadState 提供,查看 PostingThreadState 类;

PostingThreadState

    final static class PostingThreadState {
        final List eventQueue = new ArrayList<>(); // 队列
        boolean isPosting;// 是否发送中
        boolean isMainThread;// 是否在主线程
        Subscription subscription;// 封装了subscriber 和 subscriberMethod
        Object event; // 事件
        boolean canceled; // 是否被取消
    }
 
 

很简单,维护了一些基础数据;

查看 postSingleEvent 发送方法;

    private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {
        Class eventClass = event.getClass();
        boolean subscriptionFound = false;
        if (eventInheritance) { // 事件父类对应的方法同时查找
            List> 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) {
                logger.log(Level.FINE, "No subscribers registered for event " + eventClass);
            }
            if (sendNoSubscriberEvent && eventClass != NoSubscriberEvent.class &&
                    eventClass != SubscriberExceptionEvent.class) {
                post(new NoSubscriberEvent(this, event));
            }
        }
    }

lookupAllEventTypes 方法会查找到对应注册了 事件类的 父类的相关信息,同时进行发送;

postSingleEventForEventType 进行发送事件;

    private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class eventClass) {
        CopyOnWriteArrayList subscriptions;
        synchronized (this) {
            subscriptions = subscriptionsByEventType.get(eventClass); // 按照事件分类的 集合;
        }
        if (subscriptions != null && !subscriptions.isEmpty()) {
            for (Subscription subscription : subscriptions) {//遍历 集合
                postingState.event = event;
                postingState.subscription = subscription;
                boolean aborted;
                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;
    }

Subscription 的结构如下;

final class Subscription {
    final Object subscriber;
    final SubscriberMethod subscriberMethod;
    /**
     * Becomes false as soon as {@link EventBus#unregister(Object)} is called, which is checked by queued event delivery
     * {@link EventBus#invokeSubscriber(PendingPost)} to prevent race conditions.
     */
    volatile boolean active;

    Subscription(Object subscriber, SubscriberMethod subscriberMethod) {
        this.subscriber = subscriber;
        this.subscriberMethod = subscriberMethod;
        active = true;
    }

    @Override
    public boolean equals(Object other) {
        if (other instanceof Subscription) {
            Subscription otherSubscription = (Subscription) other;
            return subscriber == otherSubscription.subscriber
                    && subscriberMethod.equals(otherSubscription.subscriberMethod);
        } else {
            return false;
        }
    }

    @Override
    public int hashCode() {
        return subscriber.hashCode() + subscriberMethod.methodString.hashCode();
    }
}

这里的 subscriptions 的获取就和之前 subscribe 绑定方法存储的信息关联上了,通过 subscriptions 可以找到,对应发送事件的 EventType 都在哪些类中进行注册了,同时获取到了注册方法的相关信息(也就是注解信息);

最后遍历集合,通过 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 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);
                } else { 
                    invokeSubscriber(subscription, event);
                }
                break;
            case ASYNC:
                asyncPoster.enqueue(subscription, event);
                break;
            default:
                throw new IllegalStateException("Unknown thread mode: " + subscription.subscriberMethod.threadMode);
        }
    }

以上根据实际发送事件所在线程,和我们定义的处理事件所在线程;进行不同的方法调用;

这里简单看下 MAIN ,即处理消息事件在主线程;
1 当我们的发送事件也是主线程的时候,调用 invokeSubscriber;
2 当我们的发送事件不是主线程,则要借用 Handler 进行处理了,这里就使用到了之前初始化的 mainThreadPoster;

实质上在 mainThreadPoster 的 HandlerPost 中,处理事件消息依然会调用到 invokeSubscriber,mainThreadPoster 只是作为消息机制的一个线程切换来使用;

其他的情况大同小异,可自行分析;

接下来,就查看 invokeSubscriber 方法了;对应的传参分别是:
1 subscription -- 包含注册事件所在类以及注册的方法;
2 event -- 事件本身;

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

通过反射调用执行事件,完成整个发送-接收过程;

现在再回到之前没有继续查看的粘性事件中,有个 checkPostStickyEventToSubscription 方法,这里应该是直接调用执行粘性事件对应的绑定方法;我们查看源代码确认是否是这样的呢?

        if (stickyEvent != null) {
            // If the subscriber is trying to abort the event, it will fail (event is not tracked in posting state)
            // --> Strange corner case, which we don't take care of here.
            postToSubscription(newSubscription, stickyEvent, isMainThread());
        }

可以看到这里调用了 postToSubscription ,和上述发送事件的方法一致,所以当我们对一个响应事件定义为粘性事件,实则相当于系统自动帮我们执行了发送事件方法。会直接调用响应事件中的处理;

到这里,EventBus的注册,到事件的处理整个基本流程就已经走完了;这里可以总结一下哪些重要步骤以及主要都是做了什么工作:
1 EventBus.getDefault(),创建响应 Poster ,对应 Poster 实则是为了处理线程的切换问题;
2 EventBus.getDefault().register();去查找项目中注解的方法,方法类型,方法名,注解所在类等集合数据,存储在本地并返回;
3 EventBus.getDefault().post(new MessageEvent("this is an event"));发送事件,对比对应本地存储的数据,同时依赖初始化建立的 Poster 切换线程;
4 粘性事件会在注册类初始化的时候立刻进行响应事件;

到这里EventBus的主要流程以及方法已经总结完了,可以看到EventBus主要用了java里面的反射方法以及Android中的handler处理机制,这里进行过多研究。
如果对handler有所疑惑;可查看探究Handler的运行机制.

你可能感兴趣的:(探究EventBus的运行原理)