Retrofit passing in suspend function
from the CommonsWare Community archivesAt November 27, 2020, 5:51pm, Jan asked:
I am trying to centralize the try{} catch{} and error handling when making retrofit API calls. Examples on the internet have a safeAPICall function that would be something like this:
class APICall {
suspend fun safeApiCall(serviceCall: suspend () -> Response): APIResult {
return try {
val response = serviceCall()
or ------
//val response = serviceCall.invoke()
if (response.isSuccessful()) {
APIResult.Success(response.body()!!)
} else {
APIResult.Error("Unsuccessful")
}
} catch (t: Throwable) {
APIResult.Error("General failure")
}
} // safeApiCall
The problem I ran into was calling this function. I get the error message
Type mismatch.
Required:
suspend () → Response<TypeVariable(T)>
Found:
SigninRequestAPI
I tried two methods of calling and they both gave this error message:
val netService = // call retrofit create on (SigninRequestAPI::class.java)
APICall().safeApiCall(netService)
and
APICall().safeApiCall(SigninRequestAPI::class.java)
The SigninRequest API is the normal Interface used with retrofit.
the examples in medium articles showing safeApiCall seemed to be just passing the function so I don’t understand what is going wrong here.
At November 27, 2020, 6:55pm, mmurphy replied:
suspend fun safeApiCall(serviceCall: suspend () -> Response) : APIResult
This would be called as:
safeApiCall {
TODO("do something that returns a Response")
}
At November 27, 2020, 7:07pm, Jan replied:
Hmm. So I put in the retrofit call inside the body of the curly braces and returned Retrofit’s response. Unfortunately, that didn’t compile either.
I guess safeAPICall is just not intended to be used except for really complex situations like in all the examples I saw in the medium articles.
I tried the call back adapter method which all the articles said would work but that wouldn’t parse my json. At this point I could have coded the try/catches everywhere instead of making the solution elegant.
At November 27, 2020, 7:22pm, mmurphy replied:
Another possibility is to use existing solutions for this sort of “convert the exceptions into dedicated classes”, such as https://github.com/slackhq/EitherNet.
At November 27, 2020, 7:31pm, Jan replied:
I tried EitherNet but it’s definitely not ready. I got a compile error just adding it in.
I tried this one: https://github.com/mlegy/retrofit2-kotlin-coroutines-call-adapter which looked very promising. But it doesn’t parse out the JSON on a successful response body. Instead it returns the Unknown Error in the onFailure callback.