Kotlin 和 Retrofit:如何处理 HTTP 400 响应?
Kotlin and Retrofit : How to Handle HTTP 400 responses?
我在 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 服务器将 return 一个 400 错误代码,以及包含特定错误信息的响应正文。但是,该请求没有格式错误;只是还有一个问题需要引起用户的注意。问题是,我不知道问题出在哪里,因为我没有得到回应;相反,我的调用因 400 错误代码而抛出异常。
我不明白如何修改我的代码以便捕获和处理 400 错误响应,并从响应正文中获取我需要的信息。这是我的 okhttp 客户端上的网络拦截器的工作吗?任何人都可以解释一下吗?
Retrofit 定义成功响应如下:
public boolean isSuccessful() {
return code >= 200 && code < 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
}
}
}
使用此代码 (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()
}
}
我在 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 服务器将 return 一个 400 错误代码,以及包含特定错误信息的响应正文。但是,该请求没有格式错误;只是还有一个问题需要引起用户的注意。问题是,我不知道问题出在哪里,因为我没有得到回应;相反,我的调用因 400 错误代码而抛出异常。
我不明白如何修改我的代码以便捕获和处理 400 错误响应,并从响应正文中获取我需要的信息。这是我的 okhttp 客户端上的网络拦截器的工作吗?任何人都可以解释一下吗?
Retrofit 定义成功响应如下:
public boolean isSuccessful() { return code >= 200 && code < 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
}
}
}
使用此代码 (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()
}
}