网络错误改造的异常处理 [英] Exception handling of network errors retrofit
问题描述
我想知道使用协程时在改造请求中处理网络错误的最佳方法是什么.
I was wondering what is the best way to handle network errors in retrofit requests when using coroutines.
经典方法是在发出请求时在最高级别处理异常:
The classic way is handling exception at highest level, when a request is made:
try {
// retrofit request
} catch(e: NetworkException) {
// show some error message
}
我发现此解决方案是错误的,它添加了许多样板代码,而是创建了一个返回错误响应的拦截器:
I find this solution wrong and it adds a lot of boilerplate code, instead I went with creating an interceptor that returns a error response:
class ErrorResponse : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
val request = chain.request()
return try {
chain.proceed(request)
} catch (e: Exception) {
Snackbar.make(
view,
context.resources.getText(R.string.network_error),
Snackbar.LENGTH_LONG
).show()
Response.Builder()
.request(request)
.protocol(Protocol.HTTP_1_1)
.code(599)
.message(e.message!!)
.body(ResponseBody.create(null, e.message!!))
.build()
}
}
}
此解决方案要好一些,但是我认为它可以改进.
This solution is a little better, however I think that it can be improved.
所以我的问题是:在没有大量样板代码的情况下(如果发生连接错误,最好使用全局处理程序)处理用户没有互联网连接的情况的正确方法是什么?
So my question is: What is the correct way to handle the cases when user doesn't have internet connection, without a lot of boilerplate code (ideally with a global handler in case of connection errors) ?
推荐答案
使用结果"包装我的回复
Using Result to wrap my response
sealed class Result<out T : Any> {
data class Success<out T : Any>(val value: T) : Result<T>()
data class Failure(val errorHolder:ErrorHolder) : Result<Nothing>()}
ErrorHolder:
ErrorHolder :
sealed class ErrorHolder(override val message):Throwable(message){
data class NetworkConnection(override val message: String, val throwable: Throwable) : ErrorHolder(message)
data class BadRequest(override val message: String, val throwable: Throwable) : ErrorHolder(message)
}
用于处理例外的扩展
suspend fun <T, R> Call<T>.awaitResult(map: (T) -> R): Result<R> = suspendCancellableCoroutine { continuation ->
try {
enqueue(object : Callback<T> {
override fun onFailure(call: Call<T>, throwable: Throwable) {
errorHappened(throwable)
}
override fun onResponse(call: Call<T>, response: Response<T>) {
if (response.isSuccessful) {
try {
continuation.resume(Result.Success(map(response.body()!!)))
} catch (throwable: Throwable) {
errorHappened(throwable)
}
} else {
errorHappened(HttpException(response))
}
}
private fun errorHappened(throwable: Throwable) {
continuation.resume(Result.Failure(asNetworkException(throwable)))
}
})
} catch (throwable: Throwable) {
continuation.resume(Result.Failure(asNetworkException(throwable)))
}
continuation.invokeOnCancellation {
cancel()
}}
这就是我进行api调用的方式:
And this how I make the api call:
suspend fun fetchUsers(): Result<List<User>> {
return service.getUsers().awaitResult { usersResponseDto ->
usersResponseDto.toListOfUsers()
}
}
这篇关于网络错误改造的异常处理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!