繁体   English   中英

Retrofit2使用RxJava的Observable概念处理HTTP 204(无内容响应)情况

[英]Retrofit2 handling HTTP 204 (No Content response ) situation with RxJava's Observable concepts

我有一个web服务,它返回一个主题的用户列表,如果该主题没有任何用户,它只返回HTTP代码204(无内容)。

这是我对该服务的改造2(在Kotlin中)

 @GET("/user/{topic}") fun getAllUserFor(@Path(value="topic",encoded=true) topic:String) :Observable<List<User>> 

我的执行是:

fun getAllUsers(topic: String, onSuccess: Consumer<List<User>>, onFail:Consumer<Throwable>){

    val api = NetworkLayer.getUserApi()

    api.getAllUserFor(topic)
            .observeOn(AndroidSchedulers.mainThread())
            .subscribeOn(Schedulers.io())
            .subscribe(onSuccess,onFail)

}

除非主题没有用户,否则工作正常,因为当没有用户服务器响应时,代码204作为例外接收。

我正在使用ScalarsConverterFactory和GsonConverterFactory来使用Retrofit2解析Json响应。

这里讨论的类似问题但他们的服务器只响应没有任何内容的http代码! 在我的情况下,当有一个或多个用户时,服务器将返回用户列表作为Json主体,当没有用户时,服务器将返回204,因此我需要处理这两种情况以及其他常见的http错误。

您可以通过实现一个运算符来实现这一点,该运算符将检查接收到的响应的状态代码是否为204:

class OnApiErrorOperator : ObservableOperator<OnApiErrorOperator.User, Response<OnApiErrorOperator.User>> {

    override fun apply(observer: Observer<in OnApiErrorOperator.User>): Observer<in Response<OnApiErrorOperator.User>> {
        return object : Observer<Response<OnApiErrorOperator.User>> {

            override fun onSubscribe(d: Disposable) {
                observer.onSubscribe(d)
            }

            override fun onNext(response: Response<OnApiErrorOperator.User>) {
                if (response.code() == 204) {
                    //return User object with empty list when response's status code is 204
                    observer.onNext(User(emptyList()))
                } else {
                    if (response.isSuccessful) {
                        observer.onNext(response.body()!!)
                    } else {
                        //don't forget to check for other statuses
                        observer.onError(OnApiServerErrorException(response.code()))
                    }
                }
            }

            override fun onError(e: Throwable) {
                observer.onError(e)
            }

            override fun onComplete() {
                observer.onComplete()
            }
        }
    }

    class User(
            @SerializedName("user_info")
            val userInfo: List<String>
    )

    class OnApiServerErrorException(val statusCode: Int) : Exception()
}

然后,您可以在您的observables链中添加操作员lift来调用它:

api.getAllUserFor(topic)
        .subscribeOn(Schedulers.io())
        .lift(OnApiErrorOperator())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(onSuccess, onFail)

标准方法是将响应包装在与adapter-rxjava2依赖项一起提供的Result中。

        @GET("/user/{topic}")
        fun getAllUserFor(@Path(value="topic",encoded=true) topic:String) :Observable<Result<List<User>>>

这样,错误也传递给你的onNext,你可以这样做:

           api.getAllUserFor(topic)
            .observeOn(AndroidSchedulers.mainThread())
            .subscribeOn(Schedulers.io())
            .subscribe{ result ->
               if(result.isError)
                   //Network Error
               result.response()?.also {
                   if(result.isSuccessful)
                       //Success
                   else{
                       //api error
                   }
            }
          }

更清洁,更简洁

检查状态

result.response?.code()

干杯!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM