Reputation: 23
I have two different response from the same endpoint. One being the actual success result data model and one being an error response model. Both json structure like this:
SuccessResponse:
{
"result":{
"id":1,
"name_en":"Stack Over Flow",
"summary":"Stack Overflow is the largest, most trusted online community for developers to learn, share their programming knowledge, and build their careers."
}
}
ErrorResponse:
{
"message": "Login Failed"
}
I can handle the success response but I can't show the error message what I get from the server. I have tried many ways but I can't do this. Here my I share my some aspect what I did
MainViewModel.kt
var job: Job? = null
val myDataResponse: MutableLiveData<HandleResource<DataResponse>> =MutableLiveData()
fun myData() {
job = CoroutineScope(Dispatchers.IO).launch {
val myDataList = mainRepository.myData()
withContext(Dispatchers.Main) {
myDataResponse.postValue(handleMyDataResponse(myDataList))
}
}
}
private fun handleMyDataResponse(myDataResponse: Response<DataResponse>): HandleResource<DataResponse>? {
if (myDataResponse.isSuccessful) {
myDataResponse.body()?.let { myDataData ->
return HandleResource.Success(myDataData)
}
}
return HandleResource.Error(myDataResponse.message())
}
I need a solution while server give me error message I want to show same error message on my front side. How can I achieve this?
Upvotes: 2
Views: 5810
Reputation: 794
private fun handleMyDataResponse(myDataResponse: Response<DataResponse>): HandleResource<DataResponse>? {
myDataResponse.body()?.let { myDataData ->
if (myDataResponse.code() == 200) {
return HandleResource.Success(myDataData )
} else {
val rawResponse = myDataData.string()
return HandleResource.Error(getErrorMessage(rawResponse))
}
}
}
fun getErrorMessage(raw: String): String{
val object = JSONObject(raw);
return object.getString("message");
}
The body of the response (be it success or failure) is response.body(). And if you want to get it as a String, then call response.body().string(). Since you want to read message object from the response you need to convert it into Json.
Upvotes: 2
Reputation: 641
If you are a following MVVM pattern then I suggest to create a sealed class for the API calls.
To handle api success and failure or network issue. Resource class is going to be generic because it will handle all kind of api response
sealed class Resource<out T> {
data class Success<out T>(val value: T): Resource<T>()
data class Failure(
val isNetworkErro: Boolean?,
val errorCode: Int?,
val errorBody: ResponseBody?
): Resource<Nothing>()
}
on the base repository while calling the API, you can return the resource whether it is success or failure.
abstract class BaseRepository {
suspend fun <T> safeApiCall(
apiCall: suspend () -> T
): Resource<T>{
return withContext(Dispatchers.IO){
try {
Resource.Success(apiCall.invoke())
} catch (throwable: Throwable){
when (throwable){
is HttpException -> {
Resource.Failure(false,throwable.code(), throwable.response()?.errorBody())
}
else ->{
Resource.Failure(true, null, null)
}
}
}
}
}
}
If you follow this pattern you'll be able to handle all the failure and success response, I hope this will help.
Upvotes: 1