Handle exception using retrofit

Viewed 228

I am using retrofit to network calls, but sometimes I face SocketTimeoutException, NoConnecton etc. What I want is to capture the exception and give the user information about it. I picked up a repository to start but was not able to figure out how to it. I want a common response from retrofit that includes error or data(if a successful call was made). I am doing this way to achieve this. This is how I am making the network calls.

 private fun registerNewUserServer(registerQ: RegisterQ): CommonEntityResponse {
    return safeApiCall(
        { APIServices.registerUser(registerQ) },
        "registerNewUserServer"
    ) as CommonEntityResponse
}

BaseRepoImp.kt

open class BaseRepoImp {
suspend fun <T : Any> safeApiCall(call: suspend () -> Response<T>, errorContext: String): Any? {

    val result: NetworkResult<T> = safeApiResult(call)
    var data: Any? = null

    data = when (result) {
        is NetworkResult.Success ->
            result.data
        is NetworkResult.Error ->
            "Ops! Its the new error."
        is NetworkResult.NoConnection ->
            "No network connection!"
        is NetworkResult.NotFoundException ->
            "The accessed url is not available anymore."
        is NetworkResult.ServerBroken ->
            "Server is broken just before you hit! We are fixing it."
        is NetworkResult.ServiceNotAvailException ->
            "Server is busy to serve you batter, Please try again."
    }
    return data
}

private suspend fun <T : Any> safeApiResult(call: suspend () -> Response<T>): NetworkResult<T> {
    val result: NetworkResult<T>
    try {
        Log.e("BaseRepoImp", "safeApiResult()")

        val response = call.invoke()
        Log.e("response", "safeApiResult($response)")
        if (response.isSuccessful) {
            return NetworkResult.Success(response.body()!!)
        } else {
            when {
                response.code() == 404 -> {
                    return NetworkResult.NotFoundException("The accessed url is not available anymore")
                }
                response.code() == 500 -> {
                    return NetworkResult.ServerBroken("Server is broken just before you hit! We are on fixing it")
                }
                response.code() == 503 -> {
                    return NetworkResult.ServiceNotAvailException("Server is busy to serve you batter, Please try again")
                }
            }
            return NetworkResult.Error(java.lang.Exception("Oppps... I was not expecting this from server"))
        }

    } catch (exception: IOException) {
        Log.e("exception", "safeApiResult($exception)")
        if (exception is NoConnectivityException) {
            return NetworkResult.NoConnection(exception)
        }  else {
            if (exception.toString().startsWith("java.io.EOFException:")) {
                Log.e("EOFException", "safeApiResult($exception)")
                val response = call.invoke()
                Log.e("calling back to api", "${call.toString()}")
                return NetworkResult.Success(response.body()!!)
            } else {
                return NetworkResult.Error(exception)
            }
        }
    }

}

private fun checkException(e: IOException) {

    Log.e("BaseRepoImpl", "checkException($e)")
}

private fun <T : Any> setErrorMessage(response: Response<T>): String {
    Log.e("BaseRepoImp", "setErrorMessage($response)")
    val code = response.code().toString()
    val message = try {
        val jObjError = JSONObject(response.errorBody()?.string())
        jObjError.getJSONObject("error").getString("message")

    } catch (e: Exception) {
        e.message
    }
    return if (message.isNullOrEmpty()) " error code = $code " else " error code = $code  & error message = $message "
}

}

NetworkResult.kt

sealed class NetworkResult<out T : Any> {
data class Success<out T : Any>(val data: T) : NetworkResult<T>()
data class Error(val error: Exception) : NetworkResult<Nothing>()
data class NoConnection(val exception: NoConnectivityException) : NetworkResult<Nothing>()
data class NotFoundException(val exception: String) : NetworkResult<Nothing>()
data class ServiceNotAvailException(val exception: String) : NetworkResult<Nothing>()
data class ServerBroken(val exception: String) : NetworkResult<Nothing>()
}

What I want to achieve in my DomainRepoImp.kt that If user make a call I expected a data like

CommonResponse(data: Any?, error: Exception)

How to do that?

0 Answers
Related