本文首发:http://prototypez.github.io/2016/04/10/rxjava-common-mistakes-1/
转载请注明出处
准备写这篇文章的时候看了下 RxJava 在 Github 上已经 12000+ 个 star 了,可见火爆程度,自己使用 RxJava 也已经有一小段时间。最初是在社区对 RxJava 一片赞扬之声下,开始使用 RxJava 来代替项目中一些简单异步请求,到后来才开始接触一些高级玩法,这中间阅读别人的代码加上自己踩的坑,慢慢积累了一些经验,很多都是新手容易犯的错误和 RxJava 容易被误解的地方。这些内容一篇文章写不完,所以我打算写成一个系列,这篇文章是这个系列的第一篇。
谨慎使用Subject
Subject
既是Observable
也是Observer
,由于它自己本身是Observer
,所以项目中任何地方都可以调用它的onNext
方法(只要能获得该 Subject 的引用)。看起来很好对不对?比起Observable.create
, Observable.from
, Observable.just
方便多了,这三个工厂方法都有一个特点,那就是所构建出来的 Observable 发射的元素是确定的,甚至在很多例子中,待发射的元素就像常量一样在编译期就已经可以确定。我在一开始学习这些入门的小例子的时候心里也在想,实际情况哪有这样简单:用户与 UI 交互的事件,移动设备网络类型的改变( WIFI 与蜂窝网络的切换),服务器推送消息的到达,这些事件何时发生和产生的数量都是在运行时才能得知,怎么可能用这些工厂方法简单地就发射几个固定的值。
直到我遇见了Subject
。我可以先创建一个一开始什么元素都不发射的Observable
(Subject
是Observable
的子类),并且同时创建对应的Subscriber
订阅这个Observable
,然后在我觉得某个 Ready 的时机,调用这个Subject
对象的onNext
方法,向它的Subscriber
发射元素。逻辑简洁,并且足够灵活,代码如下所示:
PublishSubject<String> subject = PublishSubject.create();
subject.map(String::length)
.subscribe(System.out::println);
...
// 在某个Ready的时机
subject.onNext("Puppy");
...
// 当某个时刻subjcet已经完成了使命
subject.onCompleted();
使用 Subject 可能导致错过真正关心的事件
到目前看来,一切都顺理成章,对比Observable
,Subject
优势明显,可以按需在合适的时机发射元素,似乎是Subject
更能满足日常任务需求,更激进一点,干脆就用Subject
来代替所有的Observable
吧。实际上,我也这么做过,但是很快就遇到了问题。举个例子,代码如下:
PublishSubject<String> operation = PublishSubject.create();
operation
.subscribe(new Subscriber<String>() {
@Override
public void onCompleted() {
System.out.println("complet