在大多数RxJava示例代码和教程中出现频率最高的类之一——Observable,是反应式编程神奇的关键。它的用法非常简单,你只需要跟踪3个事件——onNext、onError和onCompleted,你可以应用上百个操作符来实现你自己的表达式。那么,为什么您需要了解其他信息?但是仔细想想,真的需要每次都知道这3个事件吗?事实上,在大多数情况下不需要它。ReactiveX文档基本上都是关于连续的事件流,所以我们经常忘记通常我们只关心监听单个事件或者只关心完成或失败的事件。在这种情况下,我们应该考虑RxJava的两个奇妙设计——Single和Completable。在分析两者之前,我们先来看一下它们的应用场景示例。本文所有代码均基于RxJava2.x,而非1.x版本。如果你还没有将RxJava升级到最新的2.x版本,强烈建议你现在就升级。单一在Android中使用RxJava最常见的场景是网络请求,你可能会使用Retrofit作为项目的Http客户端。假设你有一个GETHTTP请求返回一些数据,并且使用RxJavaAdapter你可能会这样写:publicinterfaceAPIClient{@GET("my/api/path")ObservablegetMyData();}上面的代码是很好,当调用它时:apiClient.getMyData().subscribe(newConsumer(){@Overridepublicvoidaccept(MyDatamyData)throwsException{//处理成功获取的数据}},newConsumer(){@Overridepublicvoidaccept(Throwablethrowable)throwsException{//处理错误事件}},newAction(){@Overridepublicvoidrun()throwsException{//处理完成事件}});仔细想想,其实这个网络请求并不是一个连续的事件流,你只会发起一个Get请求返回数据,只接收一个事件。我们都知道在这种情况下onComplete会在onNext之后立即被调用,那么为什么不将它们合二为一呢?在上面的案例中,为了更清楚地体现请求的意图,应该将Observable替换为Single。从官方文档中对Single的描述,你可以找到为什么它是最合适的选择:Single有点像Observable,但它不是发出一系列值——从没有到无限的任何地方——它总是发出一个值或错误通知。所以修改后的API客户端是这样的:publicinterfaceAPIClient{@GET("my/api/path")SinglegetMyData();}同时请求的调用也可以简化:getMyData().subscribe(newConsumer(){@Overridepublicvoidaccept(MyDatamyData)throwsException{//处理成功获取的数据并完成API调用}},newConsumer(){@Overridepublicvoidaccept(Throwablethrowable)throwsException{//处理错误事件}});最欣慰的是,Single基本实现了所有的Observable操作符——map、flatMap、filter、zip等,如果你发现需要使用一个Observable操作符而Single不支持,你可以将Single转换为Observable使用toObservable运算符。apiClient.getMyData().toObservable()//现在这是一个Observable如果您有一个行为类似于Single的Observable,它也可以通过singleOrError运算符转换为Single。Completable继续讨论Retrofit的例子,然后看另一个常见的场景——通过PUT请求更新数据。我们修改一个MyData类型的对象的一些属性,然后发送到服务器,更新服务器数据库。大多数服务器API设计成功后返回更新的对象,所以你的API客户端实现是:publicinterfaceAPIClient{@PUT("my/api/updatepath")ObservableupdateMyData(@BodyMyDatadata);}同样,类似于前面的例子,应该这样调用:apiClient.updateMyData(myUpdatedData).subscribe(newConsumer(){@Overridepublicvoidaccept(MyDatamyData)throwsException{//处理成功获取的数据和API调用完成}},newConsumer(){@Overridepublicvoidaccept(Throwablethrowable)throwsException{//处理错误事件}},newAction(){@Overridepublicvoidrun()throwsException{//处理完成-我们真正关心的是什么}});你可能会说我们这里也可以用Single来简化代码,没错。在这种情况下,我们仍然需要MyData结果,确定吗?服务器向我们返回更新的数据是一个很好的设计,而实际上它只是返回我们之前发送给它的对象。我们真正需要的只是更新成功,这意味着,我只关心onComplete事件。这也是引入Completable的原因。官方文档是这样描述的:表示一个没有任何值的计算,只是指示完成或异常。使用Completable时,我们忽略onNext事件,只处理onComplete和onError事件。API客户端重写为:publicinterfaceAPIClient{@PUT("my/api/updatepath")CompletableupdateMyData(@BodyMyDatadata);}callsas:apiClient.updateMyData(myUpdatedData).subscribe(newAction(){@Overridepublicvoidrun()throwsException{//处理完成}},newConsumer(){@Overridepublicvoidaccept(Throwablethrowable)throwsException{//处理错误}});Completable与Observable和Single本质上不同,因为它不发射数据。所以Completable的操作符也不同,最常用的是andThen。在这个操作符中你可以传递任何Observable、Single、Flowable、Maybe或其他Completable,它们将在原始Completable结束后执行。例如。你想执行一些其他操作(Single):apiClient.updateMyData(myUpdatedData).andThen(performOtherOperation())//aSingle.subscribe(newConsumer(){@Overridepublicvoidaccept(OtherResultresult)throwsException{//handleotherResult}},newConsumer(){@Overridepublicvoidaccept(Throwablethrowable)throwsException{//handleerror}});与Single不同,RxJava不允许直接将Observable转换为Completable,因为没有办法知道一个Observable何时完成。但是你可以把Single转成Completable,因为Single保证会调用onComplete,而这个算子就是toCompletable。希望这个对Single和Completable的简短介绍能帮助您理解这两个概念并编写更简洁的代码。