如何处理 Retrofit 2.0 中的错误

Posted

技术标签:

【中文标题】如何处理 Retrofit 2.0 中的错误【英文标题】:How to handle error in Retrofit 2.0 【发布时间】:2016-11-13 05:53:39 【问题描述】:

我想处理 Retrofit 2.0 中的错误

得到例如code=404body=null,但 errorBody() 包含 ErrorModel 中的数据(Boolean statusString info)。

这是errorBody().content[text=\n"status":false,"info":"Provided email doesn't exist."]

我怎样才能得到这些数据?

谢谢你帮助我!

这是我的改造请求代码:

ResetPasswordApi.Factory.getInstance().resetPassword(loginEditText.getText().toString())
    .enqueue(new Callback<StatusInfoModel>() 
        @Override
        public void onResponse(Call<StatusInfoModel> call, Response<StatusInfoModel> response) 
            if (response.isSuccessful()) 
                showToast(getApplicationContext(), getString(R.string.new_password_sent));
             else 
                showToast(getApplicationContext(), getString(R.string.email_not_exist));
            
        

        @Override
        public void onFailure(Call<StatusInfoModel> call, Throwable t) 
            showToast(getApplicationContext(), "Something went wrong...");
        
    );

【问题讨论】:

你能放一些代码吗 你的意思是这段代码? 【参考方案1】:

如果您想在错误响应出现时获取数据(通常是除了 200 之外的响应代码),您可以在 onResponse() 方法中这样做:

if (response.code() == 404) 
    Gson gson = new GsonBuilder().create();
    YourErrorPojo pojo = new YourErrorPojo();
    try 
         pojo = gson.fromJson(response.errorBody().string(), YourErrorPojo.class);
         Toast.makeText(context, pojo.getInfo(), Toast.LENGTH_LONG).show();
     catch (IOException e)  
      // handle failure at error parse 
  

生成YourErrorPojo.class时,请执行以下步骤:

    转到Json Schema 2 Pojo

    粘贴您的示例Json,并选择源类型Json,注释Gson

    您的示例Json 是:"status":false,"info":"Provided email doesn't exist."

    点击Preview,它会为你生成Pojo类。

将此添加到您的build.gradlecompile 'com.google.code.gson:gson:2.7'

我在这个解决方案中使用了Gson,但你可以使用response.errorBody().string()获取你的Json字符串:response.errorBody().string()

【讨论】:

我试过这个代码:Gson gson = new GsonBuilder().create();StatusInfoModel error = new StatusInfoModel();try error = gson.fromJson(response.errorBody().string(), StatusInfoModel.class);showToast(getApplicationContext(), error.getInfo()); catch (IOException e) // handle failure to read error ,但是有一个错误:Class must either be declared abstract or implement abstract method @y07k2 你能提供截图我去看看吗? s32.postimg.org/eww0vfotx/error.png。当我删除else 语句错误消失。 @y07k2 啊,我看到了你的错误,因为我错过了一个 "" ,我将它添加到我的答案中。请查看已编辑的答案。 完美运行!谢谢! :)知道如何简化它(我的意思是放入方法并在不同的地方调用它)?【参考方案2】:

Retrofit 不会将 404 视为失败,因此会进入 onSuccess。

response.isSuccessful()如果响应码在200-300的范围内为真,则在此处输入else。

if (response.isSuccessful()) 
    showToast(getApplicationContext(), getString(R.string.new_password_sent));
 else 
    // A 404 will go here

    showToast(getApplicationContext(), getString(R.string.email_not_exist));

但是,由于您的响应不成功,因此您不会获得带有.body() 的响应正文,而是带有errorBody(),当请求成功时将填充errorBody,但response.isSuccessful() 返回false(因此在不是 200-300 的状态码)。

【讨论】:

是的,我知道可以这样完成,但我不想每次都输入String errorMsg,当我可以(至少我相信我可以)从errorBody() 得到的时候. errorBody 用于发生错误时,不适用于404的情况。404被视为成功 这很奇怪。为什么我在errorBody() 中收到这些数据,而不是在body() 中? 我的错。 errorBody 包含响应不成功时的响应。所以万一没有错误,但状态码不是200-300。如您所说,状态码 404 将在 errorBody 中得到响应 "response.isSuccessful() 如果响应代码在 200-300 范围内,则为 true" 准确地说:以 2XX 开头的 http 响应是成功,3XX 重定向,4XX 客户端错误和5XX 服务器端错误。【参考方案3】:

我正在使用这个库Retrobomb,您不必在该级别进行序列化。 它易于使用和定制。它支持每个错误类型或错误代码的注释。 如果您愿意,您可以解开所有错误并自行处理。

@ErrorMapping(code = 401, errorType = Unauthorized.class)
@PATCH("/v1/widgets/id")
  Single<Widget> updateWidget(@Path("id") String id, @Body Widget widget);

【讨论】:

【参考方案4】:

如果您想在错误响应出现时获取数据(通常是响应代码,除了 200),您可以在 onResponse() 方法中这样做:

override fun onResponse(call: Call<LoginData>?, response: Response<LoginData>?) 
    if (response != null) 
        if (response.code() == 200 && response.body() != null) 
            val loginData = response.body()
            if (loginData != null) 
                //Handle success case...
            
         else if (response.code() == 401) 
            val converter = ApiClient.getClient()?.responseBodyConverter<ErrorResponseData>(
                ErrorResponseData::class.java,
                arrayOfNulls<Annotation>(0))
            var errorResponse: ErrorResponseData? = null
            errorResponse = converter?.convert(response.errorBody())
            if (errorResponse != null) 
                //Handle Error case..
            
        
    

【讨论】:

【参考方案5】:

对于 Kotlin:

只需按照此代码将您的 errorBody 转换为您的响应:

if(response.isSuccessful)
     val data = response.body()!!
               
 else 
    val gson = GsonBuilder().create()

    try 
        var pojo = gson.fromJson(
            response.errorBody()!!.string(),
            CommentResponse::class.java)
            Log.e("ERROR_CHECK","here else is the error$pojo")

      catch (e: IOException) 
           // handle failure at error parse
  

【讨论】:

以上是关于如何处理 Retrofit 2.0 中的错误的主要内容,如果未能解决你的问题,请参考以下文章

JPA 2.0 如何处理死锁(Eclipselink JPA2.0 MySQL)

改造2如何处理有时无效有时非无效的服务器响应

如何处理c#中的错误代码

如何处理 VBA 中的 DLL 错误?

如何处理mio中的错误?

如何处理 NSPersistentContainer.loadPersistentStores 中的错误?