android 如何在Kotlin+retrofit+coroutine+mvvm中处理从服务器API返回的错误响应

wi3ka0sx  于 2022-12-21  发布在  Android
关注(0)|答案(2)|浏览(233)

我有两个来自同一端点的不同响应。一个是实际成功结果数据模型,一个是错误响应模型。两个json结构都是这样的:

成功响应:

{
   "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."
   }
}

错误响应:

{
    "message": "Login Failed"
}

我可以处理成功响应,但是我不能显示从服务器得到的错误消息。我尝试了很多方法,但是我不能做到这一点。在这里我分享我所做的一些方面

主视图模型.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())
    }

我需要一个解决方案,而服务器给予我错误消息我想在我的正面显示相同的错误消息。我该如何实现这一点?

ar5n3qh5

ar5n3qh51#

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");
}

响应(成功或失败)的主体是response.body()。如果你想得到一个字符串,那么调用response.body().string()。因为你想从响应中读取消息对象,你需要把它转换成Json。

mu0hgdu0

mu0hgdu02#

如果您遵循MVVM模式,那么我建议为API调用创建一个密封类。
处理API成功和失败或网络问题。资源类将是通用的,因为它将处理所有类型的api响应

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>()

}

调用API时,您可以返回资源,无论是成功还是失败。

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)
                    }
                }
            }
        }
    }
}

如果你遵循这个模式,你将能够处理所有的失败和成功的React,我希望这将有所帮助。

相关问题