【问题标题】:Retrofit2 handling HTTP 204 (No Content response ) situation with RxJava's Observable conceptsRetrofit2 使用 RxJava 的 Observable 概念处理 HTTP 204(无内容响应)情况
【发布时间】:2018-10-27 10:54:04
【问题描述】:

我有一个 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 响应。

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

【问题讨论】:

    标签: android rx-java retrofit2 okhttp


    【解决方案1】:

    标准方式是将响应包装在带有适配器-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()
    

    干杯!

    【讨论】:

    • 根据这种方法,所有的网络错误都会出现在'onNext'中,我们需要在'onNext'中处理这些错误,不是吗?
    • 是的。结果包含所有相关数据
    • 尽管从 Result 扩展,我似乎没有在 result 中得到响应对象
    • 啊 Kotlin 已经有了某种 Result 类型。我必须专门导入retrofit2.adapter.rxjava2.Result
    • 这真的很新
    【解决方案2】:

    您可以通过实现一个运算符来检查收到的响应的状态码是否为 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)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-03-30
      • 2016-09-04
      • 1970-01-01
      • 1970-01-01
      • 2018-09-06
      • 2017-01-20
      • 2021-06-30
      • 2016-11-05
      相关资源
      最近更新 更多