【问题标题】:How can we handle different response type with Retrofit 2?我们如何使用 Retrofit 2 处理不同的响应类型?
【发布时间】:2016-06-05 15:07:59
【问题描述】:

我有一个 web 服务,它返回一个序列化的 MyPOJO 对象列表:

[
  { //JSON MyPOJO },
  { //JSON MyPOJO }
]

一个错误对象:

{  
  'error': 'foo', 
  'message':'bar' 
}

使用retrofit2,如何找回错误?

Call<List<MyPOJO>> request = ...
request.enqueue(new Callback<List<MyPOJO>>() {
  @Override
  public void onResponse(Response<List<MyPOJO>> response) {
      if (response.isSuccess()) {
          List<MyPOJO> myList = response.body();
          // do something with the list...
      } else {
          // server responded with an error, here is how we are supposed to retrieve it
          ErrorResponse error = ErrorResponse.fromResponseBody(apiService.getRetrofitInstance(), response.errorBody());
          processError(error);
          // but we never get there because GSON deserialization throws an error !
      }
  }

  @Override
  public void onFailure(Throwable t) {
    if(t instanceof IOException){
        // network error 
    }else if(t instanceof IllegalStateException){
        // on server sending an error object we get there
        // how can I retrieve the error object ?
    }else { 
        // default error handling 
    }       
  }
}

这是 GSON 异常:

java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $

Retrofit 实例是使用 GsonConverterFactory 创建的

【问题讨论】:

标签: android retrofit2


【解决方案1】:

我遇到了类似的问题,我通过使用通用 Object 解决了它,然后使用 instanceof 测试了我的响应类型

Call<Object> call = api.login(username, password);
call.enqueue(new Callback<Object>() 
{
    @Override
    public void onResponse(Response<Object> response, Retrofit retrofit)
    {
         if (response.body() instanceof MyPOJO )
         {
            MyPOJO myObj = (MyPOJO) response.body();
            //handle MyPOJO 
         }
         else  //must be error object
         {
            MyError myError = (MyError) response.body();
            //handle error object
         }
    }

    @Override
    public void onFailure(Throwable t) 
    {
     ///Handle failure
    }
});

在我的情况下,我返回了 MyPOJO 或 MyError,我可以确定它会是其中之一。

在其他情况下,无论请求是否成功,我都会让后端返回相同的响应对象。
然后在这个响应对象中,我在“对象”字段中有我的实际数据。然后我可以使用 instance of 来确定我拥有什么类型的数据。在这种情况下,无论调用是什么,我总是返回相同的对象。

public class MyResponse {

    private int responseCode;
    private String command;
    private int errorno;
    private String errorMessage;
    private Object responseObject;   //This object varies depending on what command was called
    private Date responseTime;
}

【讨论】:

  • java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap 无法转换为 models.NewOrder
  • 对象对象 = response.body(); LinkedTreeMap t = (LinkedTreeMap) 对象; progress.dismiss(); Log.d("printT", "onResponse:" + t); String message = t.get("message").toString();
【解决方案2】:
Call<LoginResponse> call = apiService.getUserLogin(usernametext, passwordtext);
    call.enqueue(new Callback<LoginResponse>() {
        @Override
        public void onResponse(Call<LoginResponse> call, Response<LoginResponse> response) {
            Log.e("responsedata","dd"+response.toString());
            if (response.code()==200) {
                showMessage(response.body().getMessage());
                Intent intent = new Intent(LoginActivity.this, MainAct.class);
                startActivity(intent);
            }
            else
                try {
                    LoginError loginError= gson.fromJson(response.errorBody().string(),LoginError.class);
                    showMessage(loginError.getMessage());
                } catch (IOException e) {
                    e.printStackTrace();
                }
        }

        @Override
        public void onFailure(Call<LoginResponse> call, Throwable t) {

        }
    });
}

【讨论】:

  • 不适合我...因为它没有达到 onresponse(),在改造内部出现错误
  • LoginError loginError= gson.fromJson(response.errorBody().string(),LoginError.class);为我工作。谢谢。
猜你喜欢
  • 1970-01-01
  • 2016-01-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-22
  • 2017-11-24
相关资源
最近更新 更多