Retrofit passing in suspend function

from the CommonsWare Community archives

At 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. :slight_smile:


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.