Kotlin和Retrofit:如何处理HTTP 400响应?

时间:2020-01-08 21:37:44

标签: android kotlin retrofit okhttp

我正在Android上使用Retrofit(2.6)来实现服务,该服务连接到Web服务器,并要求服务器承担一些工作。相关代码可以总结如下:

interface MyService {
    @GET(START_WORK)
    suspend fun startWork(@Query("uuid") uuid: String,
                          @Query("mode") mode: Int):
        MyStartWorkResponse
}

// Do some other things, include get a reference to a properly configured
// instance of Retrofit.

// Instantiate service
var service: MyService = retrofit.create(MyService::class.java)

我可以毫无问题地致电service.startWork()并获得有效的结果。但是,在某些情况下,Web服务器将返回400错误代码,其响应正文包含特定的错误信息。但是,该请求没有格式错误;只是有另一个问题应该引起用户的注意。麻烦在于,我无法分辨出问题所在,因为我没有得到回应。相反,由于400错误代码,我的呼叫引发了异常。

我不知道如何修改代码,以便可以捕获和处理400个错误响应,并从响应正文中获取所需的信息。这是我的okhttp客户端上的网络拦截器的工作吗?谁能阐明一些想法?

2 个答案:

答案 0 :(得分:1)

使用此代码(KOTLIN)

class ApiClient {

companion object {

private val BASE_URL = "YOUR_URL_SERVER"
private var retrofit: Retrofit? = null

private val okHttpClientvalor = OkHttpClient.Builder()
    .connectTimeout(90, TimeUnit.SECONDS)
    .writeTimeout(90, TimeUnit.SECONDS)
    .readTimeout(90, TimeUnit.SECONDS)
    .build()

fun  apiClient(): Retrofit {

    if (retrofit == null) {
        retrofit = Retrofit.Builder().baseUrl(BASE_URL)
            .client(okHttpClientvalor)
            .addConverterFactory(GsonConverterFactory.create())
            .build()
    }
    return retrofit!!
}

}

}

object ErrorUtils {

fun parseError(response: Response<*>): ErrorResponce? {
    val conversorDeErro = ApiClient.apiClient()
        .responseBodyConverter<ErrorResponce>(ErrorResponce::class.java, arrayOfNulls(0))
    var errorResponce: ErrorResponce? = null
    try {
        if (response.errorBody() != null) {
            errorResponce = conversorDeErro.convert(response.errorBody()!!)
        }
    } catch (e: IOException) {
        return ErrorResponce()
    } finally {
        return errorResponce
    }
}

}

class ErrorResponce {
 /*This name "error" must match the message key returned by the server.
  Example: {"error": "Bad Request ....."}*/
@SerializedName("error")
@Expose
var error: String? = null

}

if (response.isSuccessful) {
    return MyResponse(response.body()//transform
            ?: //some empty object)
} else {
        val errorResponce = ErrorUtils.parseError(response)
        errorResponce!!.error?.let { message ->
        Toast.makeText(this,message,Toast.LENGTH_SHORT).show()
     }
}

答案 1 :(得分:0)

改装将成功的响应定义为:

布尔boolean isSuccessful(){ 返回代码> = 200 &&代码<300; }

这意味着您应该能够执行类似的操作

class ServiceImpl(private val myService: MyService) {
   suspend fun startWork(//query): MyResponse =

    myService.startWork(query).await().let {

    if (response.isSuccessful) {
        return MyResponse(response.body()//transform
                ?: //some empty object)
    } else {
        throw HttpException(response)//or handle - whatever
    }
}

}