EventBus框架初解

EventBus其实解决了这样几个问题:保存订阅者、发布事件、切换线程、粘性事件

保存订阅者

在register(this)时,处理运行时注解,根据this找到类和类中的方法,根据方法的Subscribe注解找到订阅事件的那些方法。
从Subscribe注解中找到指定的线程、优先级、粘滞等;
从方法参数中找到订阅的事件类eventType;
生成订阅者Subscription对象,内有订阅的类和方法的引用
然后用eventType做key,把订阅者存入concurrentHashMap中,因为一个eventType可能有多个订阅者,而且是典型读多写少的场景,所以用CopyOnWriteArrayList来保存这些订阅者。

发布事件

在post时,根据eventType,从concurrentHashMap中寻找订阅者。
会根据父类查找,eventType是根据对象的类和父类一起判断的,所以会根据一个类的列表去查询订阅者。
会排队处理,为了确保一个接一个地发送事件,post其实是先进入队列Queue,然后每次从队列中弹一个event来处理的,这个队列是个普通的List,实际上作为FIFO处理。

切换线程

同一个事件的不同订阅者,可能需要不同的线程去执行。
在找到订阅者处理时,根据订阅者要求的线程模式,做个switch处理:

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

可以看到,有默认、mainThreadPoster、backgroundPoster、asyncHandler四类。
默认会在当前线程直接invokeSubscriber,传递事件给订阅者。
mainThreadPoster其实就是一个持有主线程Looper的handler,利用handler消息机制,实现在主线程的handleMessage函数里调用eventbus的invokeSubscriber。
backgroundPoster和asyncPoster都是Runnable,都是获取eventbus中的ExecutorService来处理,不过
asyncPoster对于队列没做什么特殊处理,每个事件都会一个线程。
而backgroundPoster做了入队列的锁同步,在出队列处理时,还可以等待1000毫秒:

PendingPost pendingPost = queue.poll(1000);

其实就是说,backgroundPoster会尽量复用线程。

粘滞消息

一般事件是订阅在先,接收在后,但是有些情况下,事件已经发送,再去订阅时还希望能拿到这个事件,这时候就需要粘性事件。
粘性事件的注册也是在注解中:

@Subscribe(sticky = true)

而粘性事件的发送也有专门的函数:

EventBus.getDefault().postSticky(new MessageEvent("xxx"));  
EventBus.getDefault().getStickyEvent(MessageEvent.class);
EventBus.getDefault().removeStickyEvent(stickyEvent); 

粘性事件的实现原理,也是EventBus维持了一个concurrentHashMap类型的stickyEvents,这个Map的key是event.Class,value则是event本身。
粘性事件的发送有两个入口:
一是postSticky,每次都会先更新stickyEvents中的数据,然后post这个event。
二是register,相当于补发事件,实现粘滞效果,具体是在每次register时,会查询stickyEvent集合中,有没有粘性事件,如果有,就补发。

参考

EventBus源码分析(三)

你可能感兴趣的:(EventBus框架初解)