导语
2014年还是大二的我看到一个前辈讲解事件驱动编程并把EventBus
和Otto
作为例子演示,那时候限于开发经验,难理解它的必要性,慢慢才体会到它的必要和便利;
场景
当你做1-2个App以上的时候会发现,随着App和业务的逐渐复杂,经常遇到这种通知依赖的场景:ActivityA的不同状态ActivityB需要获取并做不同处理,包括Activity和Fragment间,尽管我们可以通过接口回调或者观察者模式来解决,如果包含层次嵌套那很难拿到需要的状态,代码无疑是冗余不优雅的;那么怎么解决呢?
- 绑定系统事件,如广播,通过发送系统广播,其他注册来对应广播的就能收到事件;But,广播是耗性能的,虽然有本地广播的存在,但还是不够优雅;
- 从借助广播能解决思考,把问题提高下层次,广播是全局的,借助系统机制便能解决,
组件间的事件通知是局部性的,低层次的;
所以,可以有一个全局性的事件管理模块;
之所以代码冗余是因为持有引用 和 回调代码;
所以,可以加一个中间层来实现解耦和简化代码;
- 思路:当低层次的局部性问题得不到较好解决时,可以上升到一定层次并较大程度解决,当模块复杂时候,也可上升到架构层次,高层抽象的解决方案往往具有较好的复用性,也为后续抽取成为基础SDK库做了准备;
什么是事件驱动编程
EventDriveDevelop;
全局–总线->EventBus
思考为何客户端才较多出现的事件驱动
移动互联网强调用户体验,用户交互事件也繁多复杂,在结合App业务,事件就比较复杂且频率高了,这点在Web前端和移动端都是同理的;
我们需要怎样的事件处理模块?
- 较高的抽象,不依赖于Android组件
- 轻量
- 性能好(第一次实现可以先忽略)
-
好用和易用
宏观目标:好用,步骤少,学习成本低
具体实现:心智负担少(不用懂得复杂的模型),封装,Api明确简洁符合直觉,暴露较少概念;
-
较低的侵入性
定位是易替换的SDK,易插拔;
一般建议开发者添加个中间层(管理类)去封装第三方SDK,进一步降低替换成本;
尝试实现
结构
- register
- ModuleA -> EventBus
- ModuleB -> EventBus
- post
- EventBubs ->(notify) ModuleA
- EventBubs ->(notify) ModuleB
从实现反推设计(自底向上)
- 我们需要怎样的使用体验?
/**
* 封装EventBus并对外暴露接口
*/
class EventBusProvider{
public static void register(Class<?> subscriberType){
EventBus.register(subscriberType);
}
public static void unRegister(Class<?> subscriberType){
EventBus.unRegister(subscriberType);
}
public static void post(Object data){
EventBus.post(data);
}
}
class ActivityA{
@Override
public void onCreate(){
// 注册到事件总线
EventBusProvider.register(this);
}
// 先默认采用惯例onEvent方法名,不用自定义注解
public void onEvent(UserLogin data){
// 此时收到回调过来的事件数据
}
}
/**
* 定义事件发生时传递的数据
*/
class UserLogin{
String userId;
String userName;
// constructor
}
class ActivityB{
private void doLogin(){
// mock
UserLogin data = new UserLogin("001","宸笙");
// 触发事件
EventBusProvider.post(data);
}
}
- 实现思路
注册
- 把订阅者如Activity的Class对象和对应的事件保存;
- Map<Object,List
>
解注册
- 和注册相反的操作,对相关集合remove操作即可;
post事件
- 实现重点:根据事件的类型找到订阅该事件的订阅组件并一一回调方法;
-
具体实现
V1;
Code;
- 使用
末
- 小结
- 延伸
- 优化点