Event Bus在安卓开发中的使用场景和技巧

观察者模式是实现模块解耦的一种非常有效的设计模式,Android里面对它支持很好的第三方库为Eventbus(https://github.com/greenrobot/EventBus) 。关于介绍Eventbus如何使用的技术文章很多,在这里我们不再累述。如果对他还不甚了解的读者,可以搜索一下相关的技术文章;这里我们只讲一下再哪些情况下需要用到Eventbus,以及如何正确使用。

先摆一下结论,Eventbus的使用需要满足的条件是:

  1. 对事件源的要求——要是真正的“事件”
  2. 对事件接受者的要求——要假设不知道接受者的数量
  3. 对事件定义的要求——事件定义要独立于事件源和事件接受者

1. 对事件源的要求

既然是“ Event ” bus,那么使用场景一定和事件相关,什么样的行为可以定义为事件呢?典型如下:

  • 用户的点击
  • 网络变化的发生
  • 用户关闭屏幕
可以看出,“事件”是那些不知道何时/何地出现的一类行为。所以可以引出我们使用Event bus的 第一个条件—— 事件源必须是真正的“Event”,观察者不知道何时何地可能发生;而不是可以预料到的“伪事件”。

比如:一个拉取某个话题下评论列表的数据请求,被设计为:
一个数据请求类 DataService.java,其中定义函数
void getComments(String udid,
		 long subjectId,
		 int start,
		 int number);
另外定义一个Event,可以获取评论:
public class GetCommentsEvent {
  private List<Comment> comments;

  public GetCommentsEvent(List<Comment> comments) {
    this.comments = comments;
  }

  public List<Comment> getComments() {
    return comments;
  }
}
调用者调用 DataService.getComments()发出请求,并监听 GetCommentsEvent事件。

这个例子的问题在于:
首先,数据的返回可以预期的,并不符合我们上面阐述的“事件”的定义(尽管数据返回的时间不确定,但是确确实实是由调用 getComments()引起的,这样的返回是可以预期的)
其次,作为一个封装良好数据请求,业务逻辑应该清晰的表达在接口当中。使用Eventbus造成了接口定义的不清晰,调用函数和事件定义是分离的,调用者需要阅读 getComments()函数的实现逻辑,才知道数据是通过GetCommentsEvent事件回调的。即使是通过注释说明回调事件,也是非常弱的约束。

正确的例子应该是形如:
void getComments(String udid,
		 long subjectId,
		 int start,
		 int number,
		 Callback<List<Comment>> callback);
函数接口本身就将需要的参数和返回的类型,以及同步/异步表达给了调用者。我们只需要看函数的定义,就知道它的作用是什么,最简单直接明了

2. 对事件接收者的要求

Eventbus使用的第二个要求是, 要假设不知道接收者的数量。换句话说,可能有很多地方在监听这个事件,而数量会根据业务需求不断变化,事先并不可知。
一个反面例子是:将函数调用过度设计为事件广播
和上面相同的场景, 拉取某个话题下评论列表,通过Eventbus设计为:
<pre name="code" class="java">public class GetCommentsEvent {
  public final String udid;
  public final long subjectId;
  public final int start;
  public final int number;

  public GetCommentsEvent(String udid, long subjectId, int start, int number) {
    this.udid = udid;
    this.subjectId = subjectId;
    this.start = start;
    this.number = number;
  }
}
 通过这样一个事件来传播。接收者接收到这个事件后,执行拉取数据的操作,但是这个事件通常情况下只有一个接收者,而不是我们所要求的“要假设不知道接受者的数量”。实际上,这样的请求完全可以通过函数来实现,比如: 
void getComments(String udid,
		 long subjectId,
		 int start,
		 int number,
		 Callback<List<Comment>> callback);


3. 对事件定义的要求

EventBus的初衷即为解耦事件的发生者和事件的接收者,事件源和事件接收者互不知晓对方的存在(表现在代码上就是没有类的依赖)。达到这个目的,就必须通过独立设计Event来实现。具体来说,事件类的定义应该在事件源和事件接收者的package之外,比如工程的目录为:


在根目录一级有一个event包,里面给出了事件的定义, 这些事件既不是在事件发生者的包内,也不是在事件接收者的包内定义的,而是整个app级别的。当然,也可以在子目录结构中定义events,但也应该遵循同样的道理,事件应该独立于发送方和接收方。








  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值