HardBirch

Event Bus —— Android开发模块间通信解耦

时间:13-07-16 栏目:Open Android/Java 作者:魔豆先生 评论:0 点击: 4,572 次

场景描述

当一个Android应用功能越来越多的时候,保证应用的各个部分之间高效的通信将变得越来越困难。

在应用中的多个地方,控件经常需要根据某个状态来更新他们显示的内容。这种场景常见的解决方式就是定义一个接口,需要关注该事件的控件来实现这个接口。然后事件触发的地方来注册/取消注册这些对该事件感兴趣的控件。

例如,陌陌依赖手机位置信息来获取附近的用户,所以在位置更新管理器(MmLocationManager)中定义了一个接口来监听位置更新的事件(MmLocationListener):

1
2
3
interface MmLocationListener {
 void onLocationChanged(Location location);
}

然后在应用的各个需要响应该事件的地方来实现上面的接口,然后在位置更新管理器(MmLocationManager)中注册/取消注册事件监听接口的实现类:

1
mLocationManager.get().register(this);

当不在需要监听的时候,取消注册

1
mLocationManager.get().unregister(this);

问题

上面的解决方案是没问题的,但是不是理想方案。每个控件实现这个接口,导致这些控件和位置管理器注册强耦合在一起。这还意味着,当单元测试的时候,您需要模拟(mocked)位置管理器来生成位置更新事件。

随着应用功能的增加,需要监听的事件越来越多,而越来越多的控件需要监听不同的事件,则导致越来越多的控件需要注册到各种事件管理器上:

1
2
3
4
5
6
// 代码开始变得无法控制…
mLocationManager.get().register(this);
userAuthenticator.get().register(this);
settingsManager.get().register(this);
syncManager.get().register(this);
configurationMonitor.get().register(this);

注意:上面的每个事件的注册,都要实现对应的时间更新接口。

注册和取消注册这些事件慢慢的会变得越来越难以管理。导致测试越来越困难,并将导致开发者的效率越来越低,同时在您的应用中越来越容易引入各种奇怪的Bug。

解决方案

为了找出该问题的优雅解决方案,从一个意想不到的的地方借鉴点经验 — Swing应用。 Event Bus模式 — 也被称为Message Bus或者发布者/订阅者(publisher/subscriber)模式 — 可以让两个组件相互通信,但是他们之间并不相互知晓。

和需要注册各个事件的监听器相比,一个组件现在只用在Event Bus上注册一次即可:

1
bus.register(this);

上面的注册告诉Event Bus我们现在希望接收各个事件的更新。 然后Bus检测该类中每个带有@Subscribe注解的函数,当相关的事件发生的时候就调用这些带有注解的函数。

上面示例中的位置监听功能,不用实现位置监听接口和里面的函数了,只需要提供一个带有@Subscribe注解的函数即可:

1
2
3
4
@Subscribe
public void locationChanged(LocationChangedEvent event) {
   // TODO React to location change.
}

现在Event Bus会把所有的LocationChangedEvent 事件都发送给上面的函数。

现在 MmLocationManager 类不用注册监听器了,当位置改变的时候 只需要向Event Bus发布事件即可:

1
bus.post(new LocationChangedEvent(37.892818, -121.772608));

这样 组件间相互解耦了,而单元测试也变得简单了。任何事件都可以发布给Event Bus,然后Event Bus会找到对该事件感兴趣的函数来调用。

注意:您也许已经发现该模式在Android上层也存在 — Intent系统就是这样设计的!

下面介绍两个Android系统的Event Bus模式类库。

 

Otto — Android系统的Event Bus类库

OttoSquare公司在他们应用中使用的Event Bus实现。从Guava中演变而来,并且专注于Android平台。

通过使用Otto,Square公司的应用组件间不紧密耦合了,单元测试也更加容易了。

您可以通过Otto项目的主页来了解更多内容或者查看Otto项目的源代码

 

EventBus — Android系统的Event Bus类库

EventBus http://greenrobot.de 出品的另外一个Event Bus类库,功能稍微多一点。

在后面的文章中将会分别介绍如何使用Otto和EventBus。

Comparison with Square's Otto

Otto is another event bus library for Android; actually it's a fork of Guava's EventBus. greenrobot's EventBus and Otto share some basic semantics (register, post, unregister, ...), but there are differences which the following table summarizes:

EventBus Otto
Declare event handling methods Name conventions Annotations
Event inheritance Yes Yes
Subscriber inheritance Yes No
Cache most recent events Yes, sticky events No
Event producers (e.g. for coding cached events) No Yes
Event delivery in posting thread Yes (Default) Yes
Event delivery in main thread Yes No
Event delivery in background thread Yes No
Aynchronous event delivery Yes No

Besides features, performance is another differentiator. To compare performance, we created an Android application, which is also part of this repository (EventBusPerformance). You can also run the app on your phone to benchmark different scenarios.

Benchmark results indicate that EventBus is significantly faster in almost every scenario:

EventBus Otto
Posting 1000 events, Android 2.3 emulator ~70% faster
Posting 1000 events, S3 Android 4.0 ~110% faster
Register 1000 subscribers, Android 2.3 emulator ~10% faster
Register 1000 subscribers, S3 Android 4.0 ~70% faster
Register subscribers cold start, Android 2.3 emulator ~350% faster
Register subscribers cold start, S3 Android 4.0 About the same

 

 

 

 

 

声明: 本文由( 魔豆先生 )原创编译,转载请保留链接: Event Bus —— Android开发模块间通信解耦

Event Bus —— Android开发模块间通信解耦:等您坐沙发呢!

发表评论


QQ群互动

Linux系统与内核学习群:194051772

WP建站技术学习交流群:194062106

魔豆之路QR

魔豆的Linux内核之路

魔豆的Linux内核之路

优秀工程师当看优秀书籍

优秀程序员,要看优秀书!

赞助商广告

友荐云推荐