EventBus源码分析
一.概述
greenrobot/EventBus是一套旨在简化Android组件间通信协作的框架,属于观察者模式的一个优秀实践,
可用于组件间的通信以及模块间的解耦。
本文基于上述源码分析其订阅/发布的实现机制和设计思想。
二.源码分析
先看下其核心类图:
EventBus采取集中控制策略,为支持多线程场景下的事件订阅/发布,采用了单例模式,使用比较轻的volatile来保证其可见性,
涉及EventBus多线程共享资源对象(如subscriptionsByEventType)的操作(如register/unregister)时采用synchronized方式保证数据
原子性和可见性。具体实现如下:
事件(订阅发布模式里也叫主题)和订阅者之间是多对多的关系,即m:n,EventBus使用了两个维度来管理事件/订阅者信息,EventBus采取了两个维度:
<1>.subscriptionsByEventType,即依据事件维度:eventA可对应subscriber1->subscriber10
<2>.typesBySubscriber,即依据订阅者维度:subscriber1可对应eventA->eventD
分两个维度管理的一个好处是检索的便利,如当eventA触发时,通过遍历subscriptionsByEventType即可快速找到所有的订阅者,执行对应的事件处理函数。
EventBus对外提供的接口很简单register/unregister/post,但也带有典型的强约束性框架特征:
事件回调的约束较强,事件处理函数只支持onEvent/onEventMainThread/onEventBackgroundThread/onEventAsync
这种方式好处:
事件回调函数名称与其线程执行特性强相关,EventBus内部实现事件订阅也更容易,用户业务代码较整洁,避免出现各种onXXX
缺点:
register时只有订阅者信息,事件的处理函数是隐式的,若不了解内部实现,会感觉很奇怪,单独定义的onEventMainThread会让人感觉和订阅操作没关联。
1.订阅
下面看下订阅的时序:
从里可以看到onEventMainThread这个事件回调的查找过程,也许EventBus不希望出现混乱的各种onXXXX事件回调,采取
强约定和反射查找的方式完成事件回调函数的注册。查找完毕后,会将subscriber和对应的Event添加到subscriptionsByEventType和typesBySubscriber。
2. 取消订阅
对应地,unsubscribe的时序如下:
本质上就是做了两个减法。
3.发布事件
前面的流程都是一样的,在执行事件回调时会根据事件类型,选择相应的线程模型执行,选择逻辑如下:
各线程模型的定义见ThreadMode类值域的源码,此处不赘述。
以EventBus中PostThread线程模型,其执行流程如下:
MainThread线程模型的post时序如下:
BackgroundThread线程模型的post时序如下:
Async线程模型的post时序如下:
4.总结
<1>.EventBus使用订阅(注册)/发布的模式,为Android组件间的通信/协作提供了很完整的一套框架
<2>.EventBus属于强约束性框架,对事件处理回调名称进行了限定,执行回调的线程模式也做了限定
<3>.EventBus体现了一种集中控制思想,通过反射机制实现,适用于对组件通信时延不敏感的场景
<4>.EventBus是否适合于业务、UI解耦存在讨论,其全局性的事件回调会产生广播风暴,场景如下:
如页面P1、P2均注册了事件eventA的监听,而从P1页面启动P2时,业务层若post(eventA),则P1和P2均会执行对应的onEvent函数,
此时P1可能是不希望接收该消息的,有同事采用MVP+EventBus的框架,MVP用于业务解耦,EventBus用于Android组件通信或全局性广播,
效果不错。
浙公网安备 33010602011771号