阅读了此问题How to deal with exception和此中级Android Networking in 2019 — Retrofit with Kotlin’s Coroutines之后,我创建了一个解决方案,其中包含一个BaseService
,该解决方案可以进行改造调用并在“链”上转发结果和异常:
API
@GET("...")
suspend fun fetchMyObject(): Response<List<MyObject>>
BaseService:
@Throws(BaseException::class)
protected suspend fun <T : Any> apiCall(call: suspend () -> Response<T>): T {
val result: Result<T> = apiResult(call)
(return when (result) {
is Result.Success -> result.data
is Result.Error -> throw result.exception
})
}
private suspend fun <T : Any> apiResult(call: suspend () -> Response<T>): Result<T> {
val response: Response<T>
try {
response = call.invoke()
} catch (t: Throwable) {
return Result.Error(mapNetworkThrowable(t))
}
if (!response.isSuccessful) {
val responseErrorBody = response.errorBody()
if (responseErrorBody != null) {
//try to parse to a custom ErrorObject
}
return Result.Error(mapHttpThrowable(Exception(), response.raw().code, response.raw().message))
}
return Result.Success(response.body()!!)
}
ChildService
suspend fun fetchMyObject(): List<MyObject> {
return apiCall(call = { api.fetchMyObject() })
}
回购
suspend fun myObjectList(): List<MyObject> {
return withContext(Dispatchers.IO) {
service.fetchMyObject()
}
}
视图模型
fun fetchMyObjectList() {
viewModelScope.launch {
try {
repo.myObjectList()
} catch (e: Throwable) {
parseError(e)
}
}
}
我认为ViewModel
(或BaseViewModel
)应该是处理异常的层,因为UI决策逻辑位于该层中,例如,如果我们只想举杯庆祝,请忽略异常类型,调用另一个函数,等等...
你怎么看?