RxJava2 / Retrofit2 - 为204 PUT和DELETE请求处理null

时间:2017-01-28 19:41:12

标签: rx-java retrofit2 okhttp3

因此,我正在使用明确定义的API,旨在不在DELETEPUT操作上返回有效负载正文。

这在Rx 0.X和Rx 1.x中是可接受的。现在我正在更新到Rx 2并且存在一个存在的危机,我应该如何处理空值。内容长度和正文当然是空的,导致:

java.lang.NullPointerException: Null is not a valid element
   at io.reactivex.internal.queue.SpscLinkedArrayQueue.offer(SpscLinkedArrayQueue.java:68)
   at io.reactivex.internal.operators.observable.ObservableObserveOn$ObserveOnObserver.onNext(ObservableObserveOn.java:116)
   at io.reactivex.internal.operators.observable.ObservableSubscribeOn$SubscribeOnObserver.onNext(ObservableSubscribeOn.java:63)
在doOnNext中

我见过很多人建议使用Optional<>,但出于使用案例的原因,我还需要支持Java7。我尝试了后端移植,但我无法让它工作。我也不想膨胀并为他们的版本导入Guava库。

我也注意到flatMap也可以帮我处理这个与地图相反的问题,而我正在阅读这些差异。

目前我有一个非常粗糙的OkHttp3拦截器,它将检查状态,检查有效负载是否为空,并添加错误的虚拟内容。

我还尝试添加转换工厂。

任何人都可以提供建议并指导我正确的道路是什么吗?当然,API可以改变,但204不应该因为它被定义为HTTP状态代码而具有有效载荷。

相关依赖

compile('com.squareup.retrofit2:retrofit:2.1.0') {
     exclude module: 'okhttp'
} 
compile 'com.squareup.retrofit2:converter-gson:2.1.0'
compile 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0'
compile 'com.squareup.okhttp3:okhttp:3.5.0'
compile 'com.squareup.okhttp3:logging-interceptor:3.5.0'

compile 'io.reactivex.rxjava2:rxjava:2.0.5'
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
compile 'com.trello.rxlifecycle2:rxlifecycle:2.0.1'
compile 'com.trello.rxlifecycle2:rxlifecycle-components:2.0.1'

3 个答案:

答案 0 :(得分:26)

您需要在Retrofit中声明您的请求方法,如:

@DELETE(...)
Call<Void> deleteFile(...args);

在RxJava中,您的Observable必须输入:

@DELETE(...)
Observable<Response<Void>> deleteFile(...args);

onNext()doOnNext(),如果请求成功,您通常会收到Response

Void不会将响应主体发送到转换器以进行进一步的反序列化。所有空回复Call都应输入为Void

答案 1 :(得分:12)

由于你有一个RxJava2和改进2,你可以使用一种更易读的方式,使用Completable从端点描述你真正想要的东西。

Completable按设计只返回onComplete()onError(Exception),这样一旦你看到它就知道发生了什么(你只关心执行而不是返回值)并且不要怀疑Response<Void>下的内容。

因此,您的端点调用应如下所示:

@DELETE(...)
Completable deleteFile(...args);

支持更多类型,请参阅Retrofit 2 RxJava 2 Adapter页面。Single是一个在api调用方面脱颖而出的类型。

答案 2 :(得分:0)

对于仍在寻找答案的人:将Void替换为一些空类可以解决我的问题。像这样:

class EmptyResponse {}

并仅使用此类代替Void