How to deal with exception
Closed this issue ยท 7 comments
How to deal with exception with Deferred await error, is there any solution for no try catch for this problem?
I fix this by extension function ,thanks
try/catch the await
thanks a lot!
try/catch the await
Is there any better way without putting all await() calls into try/catch? This solution is not preferred for apps with many network requests
I'm looking for a solution like the one @hossein-amini is looking for.
It's really inconvenient deal with try/catch
for each call.
As I comment here #46 (comment)
i'm pretty new to kotlin so that surely can be improved (looking forward to it) but i've come up with:
suspend fun <A, T> toSuspendAwait(fn: (A) -> Deferred<Response<T>>)
: suspend (A) -> Response<T>? = { a: A ->
try {
fn(a).await()
}
catch (e: Exception) {
Log.w("[APIAccess]","toSuspendAwait(): call thrown: ${e.message}")
null
}
}
and another one with no params for 'fn', then you call it like (squeezed to minimum):
interface APIAccess {
@POST("/reservation")
fun reservation(@Body body : ReservationCommand): Deferred<Response<ReservationResponse>>
}
private val mRetrofitService: Retrofit = makeRetrofitService()
private val mAPI: APIAccess = mRetrofitService.create(APIAccess::class.java)
val reservationResponse = toSuspendAwait(mAPI::reservation)(
ReservationCommand(
vehicle.externalId,
vehicle.provider,
providerStoredCredentials.getAuthToken().accessToken
)
)
reservationResponse?.body()? < do something >
this way the reservationResponse
will be null
if request thrown exception.
I bet somebody can do better! :)
Using @rrozek code I manage to capture exception just once in my project.
open class BaseRepository{
suspend fun <T : Any> safeApiCall(call: suspend () -> Response<T>): Resource<T>? {
return safeApiResult(call, "Error")
}
private suspend fun <T: Any> safeApiResult(call: suspend ()-> Response<T>, errorMessage: String) : Resource<T>{
return try {
val response = call.invoke()
if(response.isSuccessful) return Resource.Success(response.body()!!)
else{
val converterError = ErrorUtils.parseError(response)
converterError.code = response.code()
return Resource.Failure(converterError)
}
} catch (se3: SocketTimeoutException) {
return Resource.Failure(Error("Error", 500))
}catch (e: Throwable) {
return Resource.Failure(Error("Error, no internet conection ", 500))
}
}
}
And then i use this BaseRository
for every repository (network calls) :
class LoginRepository (private val api : ApiServer): BaseRepository(){
suspend fun login(license: String, pass: String) : Resource<AuthenticateResponse>?{
return safeApiCall(call = { api.login(license, pass, true).await()}
)
}
Also read: https://android.jlelse.eu/android-networking-in-2019-retrofit-with-kotlins-coroutines-aefe82c4d777 --> good tutorial of how to use this library and create a baserepository