Android常见的Event-driven方案
2015-11-25 19:24
267 查看
分析Android常用的Event-driven方案,分析各自的设计思路,使用方式,优势劣势;方便在项目中针对性使用,也为设计自己的EDA(Event-driven Architecture)作铺垫。
1. 机制简单,高效;
2. 接口表意明确,易于理解。
劣势:
1. 需要声明一堆XXXListener,以及对应的注册和注销函数。
2. 强依赖XxxManager。
3. 不利于测试,如果要测试,必须对XxxMananger进行mock。
1. Android SDK支持,可以现成拿来使用;
2. 支持跨进程通知;
3. 使用Atlas时,未加载的bundle也能收到广播,无缝兼容Atlas懒加载;
4. 发布者和订阅者基于字符串约定,解耦彻底;
5. 测试时只需要模拟广播就可以了,测试方便。
劣势:
1. 注册广播和发送广播时操作比较麻烦;
2. 静态注册的广播无法注销;
3. 由于支持跨进程,支持跨APP,所以容易产生安全问题;
4. 消息派发的线程支持不如EventBus;
5. 由于是发送的广播各个进程都会收到,因此如果几个进程发送同一个消息时,容易混淆。
1. 相比Basic Broadcast更加轻量级,由于是在进程内部的,所以更加安全。
2. Android SDK支持,可以现成使用;
3. 发布者和订阅者基于字符串约定,解耦彻底,测试方便;
4. 测试时只需要模拟广播就可以了,测试方便。
劣势:
1. 注册广播和发送广播时操作比较麻烦;
2. 和Basic Broadcast相比,不支持跨进程通知;
3. 当使用Atlas时,如果bundle未加载,无法收到Local Broadcast;
4. 消息派发的线程支持不如EventBus。
1. 发布者和订阅者,是基于消息的Class Type来约定的,相比字符串更加直观;
2. 接口简单易用;
3. SDK很小,接入成本低;
4. 和EventBus相比,用注解来标记消息处理函数,不容易出错;
劣势:
1. 发布者和订阅者之间的消息Class是耦合的,如果分模块开发,解耦不如用字符串约定的彻底;
2. 订阅的消息类型是通过消息的Class Type来区分的,因此每一个消息得声明一个类,大规模使用会有很多消息Class;
3. 由于使用注解,和EventBus相比,效率更低。
1. 发布者和订阅者,是基于消息的Class Type来约定的,相比字符串更加直观;
2. 接口简单易用;
3. SDK很小,接入成本低;
4. 和EventBus相比,效率更高。
劣势:
1. 发布者和订阅者之间的消息Class是耦合的,如果分模块开发,解耦不如用字符串约定的彻底;
2. 订阅的消息类型是通过消息的Class Type来区分的,因此每一个消息得声明一个类,大规模使用会有很多消息Class;
3. 消息处理函数是通过命名约定的,容易写错,且因为没有实现接口,所以写错了也不能在编译期发现问题。
Otto http://square.github.io/otto/
EventBus https://github.com/greenrobot/EventBus
Decoupling Android App Communication with Otto https://corner.squareup.com/2012/07/otto.html
Event-driven programming for Android https://medium.com/google-developer-experts/event-driven-programming-for-android-part-i-f5ea4a3c4eab#.7bvzu9802
Android开发中的Event Driven http://xhrwang.me/2015/05/09/event-driven-in-android.html
What is Event-driven Architecture http://searchsoa.techtarget.com/definition/event-driven-architecture
1.Listener
最普通的事件驱动设计,观察者实现一个listener,注入到事件生产者中,获取事件的回调。1.1 解决的问题
将事件产生者,和事件监听者解耦开来,使事件监听者可替换,可增加减少。1.2 使用例子
//1.实现接口 private listener = new OnXXXListener(){ public void onXXX() { //do something } } //2.注册监听 XxxManager.registerOnXXXListener(listener); //3.注销监听 XxxManager.unregisterOnXxxListener(listener); //4.通知监听者 if (listener != null){ listener.onXXX(); }
1.3 优劣分析
优势:1. 机制简单,高效;
2. 接口表意明确,易于理解。
劣势:
1. 需要声明一堆XXXListener,以及对应的注册和注销函数。
2. 强依赖XxxManager。
3. 不利于测试,如果要测试,必须对XxxMananger进行mock。
2.Basic Broadcast
使用Android提供的BroadcastReceiver组件,订阅者需要继承BroadcastReceiver类,并用IntentFilter来声明自己关注的消息。消息默认在主线程中派发。2.1 解决的问题
将事件产生者,和事件处理者之间的依赖彻底解耦,双方都只需依赖系统提供的Context。并且BroadcastReceiver作为基础组件,可以用于跨APP,跨进程传递消息。2.2 使用例子
//1.实现Receiver public class XxxReceiver extends BroadcastReceiver{ public void onReceive(Context context, Intent intent){ //do something } } //2.注册广播(在AndroidManifest.xml中注册) <receiver android:name="com.xxx.XxxReceiver" > <intent-filter> <action android:name="xxx" /> </intent-filter> </receiver> //2.注册广播(动态注册) XxxReceiver receiver = new XxxReceiver(); IntentFilter filter = new IntentFilter(action); context.registerReceiver(receiver, filter); //3.注销广播(仅针对动态注册的Receiver) context.unregisterReceiver(receiver); //4.发布广播 Intent intent = new Intent(action); context.sendBroadcast(intent);
2.3 优劣分析
优势:1. Android SDK支持,可以现成拿来使用;
2. 支持跨进程通知;
3. 使用Atlas时,未加载的bundle也能收到广播,无缝兼容Atlas懒加载;
4. 发布者和订阅者基于字符串约定,解耦彻底;
5. 测试时只需要模拟广播就可以了,测试方便。
劣势:
1. 注册广播和发送广播时操作比较麻烦;
2. 静态注册的广播无法注销;
3. 由于支持跨进程,支持跨APP,所以容易产生安全问题;
4. 消息派发的线程支持不如EventBus;
5. 由于是发送的广播各个进程都会收到,因此如果几个进程发送同一个消息时,容易混淆。
3.Local Broadcast
使用LocalBroadcast,也是Android SDK提供,使用方式和Basic Broadcast很类似,区别在于它是进程内部的,所以更加轻量级,也更加安全。3.1 解决的问题
将事件产生者,和事件处理者之间的依赖彻底解耦,双方都只需依赖LocalBroadcastManager。由于Basic Broadcast是重量级的广播,LocalBroadcast的设计是为了进程内部的使用场景。3.2 使用例子
//1.定义一个Receiver private BroadcastReceiver receiver = new BroadcastReceiver() { public void onReceive(Context context, Intent intent){ //do something } } //2.注册广播 IntentFilter filter = new IntentFilter(action); LocalBroadcastManager.getInstance(context).registerReceiver(receiver, filter); //3.注销广播 LocalBroadcastManager.getInstance(context).unregisterReceiver(receiver); //4.发布广播 Intent intent = new Intent(action); LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
3.3 优劣分析
优势:1. 相比Basic Broadcast更加轻量级,由于是在进程内部的,所以更加安全。
2. Android SDK支持,可以现成使用;
3. 发布者和订阅者基于字符串约定,解耦彻底,测试方便;
4. 测试时只需要模拟广播就可以了,测试方便。
劣势:
1. 注册广播和发送广播时操作比较麻烦;
2. 和Basic Broadcast相比,不支持跨进程通知;
3. 当使用Atlas时,如果bundle未加载,无法收到Local Broadcast;
4. 消息派发的线程支持不如EventBus。
4.Otto
Otto是square基于guava设计的EDA,和LocalBroadcast相比,他的订阅者不需要实现框架提供的接口,只需要自己实现一个单参数的函数,并且有注解标记该函数处理event即可。4.1 解决的问题
将事件产生者,和事件处理者之间的依赖彻底解耦,双方都只需依赖Bus。其使用场景和LocalBroadcast是一致的,只是接口设计不太一样,为了使用上更加简洁。4.2 使用例子
//1.定义一个消息类型 public class XxxEvent{ //some filds } //2.声明Bus实例,一般是单例使用 Bus bus = new Bus(); //3.注册订阅者 //实现一个用来处理消息的函数,用@Subscribe标记,只能有一个参数 @Subscribe public void onXxxEvent(XxxEvent event){ //do something } //注册 bus.register(this); //4.注销 bus.unregister(this); //5.发布消息 XxxEvent event = new XxxEvent(); bus.post(event);
4.3 优劣分析
优势:1. 发布者和订阅者,是基于消息的Class Type来约定的,相比字符串更加直观;
2. 接口简单易用;
3. SDK很小,接入成本低;
4. 和EventBus相比,用注解来标记消息处理函数,不容易出错;
劣势:
1. 发布者和订阅者之间的消息Class是耦合的,如果分模块开发,解耦不如用字符串约定的彻底;
2. 订阅的消息类型是通过消息的Class Type来区分的,因此每一个消息得声明一个类,大规模使用会有很多消息Class;
3. 由于使用注解,和EventBus相比,效率更低。
5.EventBus
EventBus是greenrobot实现的EDA,其设计和Otto很像,不同之处在于,首先EventBus处理消息的函数是通过命名约定,而不是像Otto那样的注解。其次,EventBus提供了更加丰富的线程支持;最后EventBus效率更高。5.1 解决的问题
将事件产生者,和事件处理者之间的依赖彻底解耦,双方都只需依赖EventBus。其使用场景和LocalBroadcast及Otto是一致的,只是接口设计不太一样,同时提供更加丰富的线程支持。5.2 使用例子
//1.定义一个消息类型 public class XxxEvent{ //some filds } //2.注册订阅者 //接受事件的函数名必须叫onEvent public void onEvent(XxxEvent event) { //do something } //注册 EventBus.register(this); //3.注销监听 EventBus.unregister(this); //4.发送消息 XxxEvent event = new XxxEvent(); EventBus.post(event);
5.3 优劣分析
优势:1. 发布者和订阅者,是基于消息的Class Type来约定的,相比字符串更加直观;
2. 接口简单易用;
3. SDK很小,接入成本低;
4. 和EventBus相比,效率更高。
劣势:
1. 发布者和订阅者之间的消息Class是耦合的,如果分模块开发,解耦不如用字符串约定的彻底;
2. 订阅的消息类型是通过消息的Class Type来区分的,因此每一个消息得声明一个类,大规模使用会有很多消息Class;
3. 消息处理函数是通过命名约定的,容易写错,且因为没有实现接口,所以写错了也不能在编译期发现问题。
总结
以上各种Event-driven方案各有特色,并没有一种方案可以cover所有case,需要针对性去使用。例如在小模块内部,用listener就显得更加清晰,内聚。但是在比较松散的模块间,用listener可能就不是一个好主意了。参考引用
Decoupling your Android code http://blog.android-develop.com/2014/03/decoupling-your-android-code.htmlOtto http://square.github.io/otto/
EventBus https://github.com/greenrobot/EventBus
Decoupling Android App Communication with Otto https://corner.squareup.com/2012/07/otto.html
Event-driven programming for Android https://medium.com/google-developer-experts/event-driven-programming-for-android-part-i-f5ea4a3c4eab#.7bvzu9802
Android开发中的Event Driven http://xhrwang.me/2015/05/09/event-driven-in-android.html
What is Event-driven Architecture http://searchsoa.techtarget.com/definition/event-driven-architecture
相关文章推荐
- Android APP 读取 AndroidManifest.xml 中的版本信息详解
- Android各种访问权限Permission
- android 开发进阶自定义控件 类似 TextView
- Android Matrix利用invert实现逆向坐标映射
- Android 第三方开源PullToRefresh加入Item(系列2)
- Android 开发中使用Fragment跳转到下一个Fragment(使用add方法),并实现返回键和自定义返回键。
- Android工程引用其他项目
- Android 第三方开源SwipeMenuListView(QQ侧滑置顶,删除)
- Android 第三方开源SwipeToDismiss:左滑/右滑删除ListView条目Item
- Android View学习相关和设置监听器的方法
- Android实战技巧:数据存储方式
- android之interpolator的用法详解
- Chromium Android版本
- Broadcast
- Android——控制ListView滚动
- Android搜索控件的基本使用方法
- Android帧动画三步骤
- Android Canvas Region.Op中的Clip方式
- 安卓开发之发送自定义广播
- Android实现Live Photos 加源代码