原文链接:Grokking RxJava, Part 3: Reactive with Benefits
在第一部分中我浏览了RxJava的基本结构,并且介绍了map操作符。在第二部分中,我介绍了RxJava操作符的强大之处。不过你仍旧很固执,因为这不足以打动你。接下来介绍RxJava其他的优势。
0x00 错误处理
直到此时,我们还没有介绍onComplete()和onError()。他们标志着Observable停止发射事件的时机和原因(成功完成或者未知错误)。
我们的初始Subscriber能够监听onComplete() 和 onError()回调。让我们用它做点什么:
Observable.just("Hello, world!")
.map(s -> potentialException(s))
.map(s -> anotherPotentialException(s))
.subscribe(new Subscriber<String>() {
@Override
public void onNext(String s) { System.out.println(s); }
@Override
public void onCompleted() { System.out.println("Completed!"); }
@Override
public void onError(Throwable e) { System.out.println("Ouch!"); }
});
potentialException() 和 anotherPotentialException()两个方法都能够抛出异常,每个Observable遇到onCompleted() 或 onError()回调时都会终止。因此,程序的可能输出”Completed!”或者”Ouch!”(如果抛出异常)。
下面有几点小提示:
1. 只要有异常抛出onError()就会调用
这简化了错误处理。我可以在单一的地方处理错误。
2. 操作符不需要处理异常
你可以把它交给Subscriber来决定如何处理异常,因为异常的onError()。
3. 你知道Subscriber 何时停止接收事件
了解任务何时完成,有助于的代码流程。(虽然一个Observable 可能永远不会完成。)。
我觉得这种模式比传统的错误处理更简单。传统方式是通过这个回调,你必须在每个回调中进行错误处理,这不但导致了重复的代码,而且每个回调必须知道如何处理错误,意味着你回调与调用者紧耦合。
采用响应式模式,Observable甚至不知道如何处理错误。操作符不需要处理错误。把错误处理交给Subscriber吧。
0x02 调度器(Schedulers)
你有一个进行长时间网络请求的App,所有你必须工作在其他线程中。不过,可以遇到点小麻烦!
多线程Android应用程序是困难的,因为你必须确保代码运行正确的线程;搞砸了,你的应用程序可能会崩溃。这里典型的异常就是在主线程外修改视图。
可以使用 subscribeOn() 和 observeOn() 两个方法来对线程进行控制,subscribeOn允许我们在指定的线程创建数据,observeOn允许我们在指定的线程发射的数据。
myObservableServices.retrieveImage(url)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(bitmap -> myImageView.setImageBitmap(bitmap));
这一切多么简单?一切都在发射到Subscriber之前运行在I/O线程。最后,在我的主线程操作视图。
强大的是subscribeOn() 和 observeOn() 可以添加到任何Observable。我们不必担心Observable或者前面的操作符做过什么,我只需把他放在每个线程之后。
有点类似AsyncTask ,我必须仔细设计我的代码,当它需要并发的时候。RxJava,保留相同的代码,只是在并发的时候添加这些操作符。
0x03 订阅(Subscriptions)
有件事情,我一直隐瞒着你。当我调用Observable.subscribe()函数返回Subscription,这代表着Observable 和你的 Subscriber建立的连接:
Subscription subscription = Observable.just("Hello, World!")
.subscribe(s -> System.out.println(s));
你可以在之后通过Subscription分离建立的连接:
subscription.unsubscribe();
System.out.println("Unsubscribed=" + subscription.isUnsubscribed());
// Outputs "Unsubscribed=true"
RxJava处理终止操作看起来多么棒,如果你使用的复杂的链式操作,使用unsubscribe 终端执行,无需考虑其他工作。
0x04 结论
请记住,这些文章是RxJava导论。相比我提到的还有更多东西等着你(例如backpressure)。我也不是所有代码都使用响应式,只要足够复杂的代码,我想分解为简单的逻辑。
最初,我计划以这篇文章作为这个系列的总结,但是有些要求在Android中使用RxJava的实例,所以就有了第四部分。我希望这个介绍能让你开始使用RxJava。如果你想了解更多,我建议阅读RxJava官方维基。记住:无限可能。