不该使用 RxJava 的一些情况

作者: rain 分类: 移动 发布时间: 2016-07-14 22:24 6 条评论

Reactive programming 是一种改变游戏规则的技术。如果您正确的使用它,则会改变您的编程方式。一年之前笔者(原文作者,下同)开始接触 RxJava 并尝试使用 RxJava 来处理 UI 事件(并且成为了 RxJavaFX 的管理者)。在使用 RxJava 一段时间后,笔者发现 RxJava 能干很多事。 并且改变了很多编程的方式和方法,从 并发到 IO 以及 业务逻辑和算法。

笔者开始到处使用 RxJava ,只要是可以用的地方就开始使用 RxJava,这样也可以更快的掌握 RxJava 的用法。

一年以后,笔者发现 RxJava 并不总是最佳的解决方案。虽然,现在笔者所写的每个应用都是 reactive 的,但是现在在有些地方可能会选择不使用 reactive 的方式来编程。需要注意的是,把任何东西转换为 Observable 是很容易的。 所以本篇文章主要介绍何时您提供的 API 应该返回非 Observable 的数据类型,如果客户端调用你的 API 的时候想使用 Observable ,则他们自己可以很容易的转换为 Observable。

第一种情况:简单的常量集合数据

这是最简单的一种不适合使用 Observable 的情况。例如有个如下的 enum 类型定义:

如果你想遍历这个枚举类型,通过下面的方式把它转换成 Observable 是不是适用所有情况呢?

如果你已经在使用 Observable 的操作符来操作数据了,这个时候使用 Observable 版本的 EmployeeType 比较合适。但是通常情况下不是这样的。

简单的常量数据并不太适合转换为 Observable 。从 API 的角度来说, 使用传统的方式来返回这种数据类型是比较好的情况。如果调用 API 的人想使用 Observable 则可以很容易的完成转换。

第二种情况:开销比较大的、缓存的对象

假设有个用来执行正则表达式搜索的 ActionQualifier 类,由于编译正则表达式是非常耗时的,所以不停的创建新的 ActionQualifier 对象是很不明智的:

如果你使用 RxJava-JDBC 并且在操作过程中使用了 ActionQualifier 对象,当有多个订阅者订阅到这个查询数据的 Observable 上的时候,由于每个订阅都会重新查询数据库,所以创建新的 ActionQualifier 是非常耗时的:

为了避免每个订阅者订阅的时候都查询一次,你可以选择使用 cache() 来缓存数据。这样的话,actionQualifiers 就没法更新了并且可能长期持有,导致虚拟机无法回收该对象。

Dave Moten 提供了一个巧妙的解决方式,缓存设定过期时间,然后重新订阅到源 Observable。但是最终你可能会问,是否可以把 actionQualifiers 保存在一个 List 中,然后手工的去刷新。

当你需要使用 Observable 的时候,则可以很容易的把 List 转换为 Observable :

不管使用哪种方式,缓存大量的消耗资源的对象都是很不好处理的。并且使用 Observable 的 cache 还会导致内存占用,根据您的具体情况,你可以灵活选择使用哪种方式。

第三种情况:简单的查看和单步的操作(Simple “Lookups” and Single-Step Monads)

RxJava 的优势之一是可以很容易的组合很多操作函数。Take these, then filter that, map to this, and reduce to that.

如果只是简单的一步操作呢?

这种情况是不是滥用 Observable 呢? 直接返回数据是不是更好呢?

如果返回的结果有多个 Category 、或者你不想处理返回数据为 null 的情况,则会使用 Observable 。但是在下面的示例中会看到,这种过度的使用 Observable 会导致更多的模板代码出现。

如果你非要这样用,则使用的时候,可以很容易的转换为 Observable:

第四种情况:经常使用到的属性(Frequently Qualified Properties)

先解释下上面提到的情况,比如有下面一个 Product 类

上面的 getCategory() 返回的是 Observable。如果你经常使用这个函数,则用起来可能相当麻烦。假设每个 Category 中有个 getGroup() 函数返回一个整数,代表所在的分组。可以根据这个分组来过滤每个组的分类:

如此简单的一个需求,代码看起来居然这么复杂到使用了 FlatMap 。如果 getCategory() 返回的是 category 对象则用起来就相当简单了:

所以针对这种经常使用到的函数或者属性,最好不要返回 Observable 的形式。

第五种情况:有状态的对象(Capturing State)

RxJava 中的数据通常是无状态的。这样可以方便并行处理多个操作。但是在实际的业务逻辑中,通常需要保留一些状态。比如打印价格时候,需要保留历史价格信息:

然后通过 Observable 的方式来获取历史信息:

但是如果这个操作是比较消耗资源的,则又回到了第二种情况。

针对这种有状态的数据,还是使用传统的查询方式比较好。

总结

使用了 RxJava,尝到了 Rxjava 的好处,您会到处使用它,但是 RxJava 是用来解决比较复杂或者非常复杂情况的,对于简单的情况还是简单处理吧。凡事要把握好度,过犹不及! 上面的一些情况,对于有经验的 RxJava 开发者可能很容易避免这种情况,对于初学者可能还处于 使用 RxJava 的蜜月期,看问题没这么透彻很容易陷入到过度使用 RxJava 的情况。

再次提醒,以上只是笔者自己的主观意见,如果有不同见解,欢迎一起讨论交流。

原文地址: http://tomstechnicalblog.blogspot.hk/2016/07/when-not-to-use-rxjava.html

本文出自 云在千峰,转载时请注明出处及相应链接。

本文永久链接: http://blog.chengyunfeng.com/?p=1009

Ɣ回顶部