【问题标题】:Retrofit callback get response body改造回调获取响应体
【发布时间】:2023-03-14 11:46:02
【问题描述】:

我正在测试 Retrofit 以将其与 Volley 进行比较,我正在努力从我的请求中获得响应。例如,我做这样的事情:

RestAdapter restAdapter = new RestAdapter.Builder()
            .setEndpoint("http://localhost:8080")
            .build();

MyService service = restAdapter.create(MyService.class);
service.getToto("toto", new Callback<Toto>() {

        @Override
        public void success(Toto toto, Response response) {
            // Try to get response body
            BufferedReader reader = null;
            StringBuilder sb = new StringBuilder();
            try {
                reader = new BufferedReader(
                    new InputStreamReader(response.getBody().in()));
                String line;
                try {
                    while ((line = reader.readLine()) != null) {
                        sb.append(line);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            String result = sb.toString();
        }

        @Override
        public void failure(RetrofitError error) {}
    });

有效,对象toto已设置,但出于测试目的,我还想显示服务器返回的JSON响应。

所以我试图从response.getBody() 读取InputStream,这是一个TypedInputStream。 不幸的是,我总是收到IOException : Stream is closed

我尝试使用 Retrofit 中的 Utils 类,但得到相同的 IOException 错误。

【问题讨论】:

  • 我认为您可以使用自定义转换器将解析委托给真正的转换器并记录服务器的响应More info here
  • 我也有同样的问题。同样简单的设置,我的实际自定义响应对象很好,填充了等等,但是当我尝试直接从响应中获取输入流时,同样的错误。但failure() 中的响应输入流工作正常
  • 实际上只是注意到了一些奇怪的事情。当我打开登录改造时,它会吐出我想看到的所有信息,我的输入流消耗工作正常,没有抛出错误。奇怪...
  • @trippedout 请看下面我的回答...
  • 您可以使用JsonObject 作为响应,然后从josnObject.toString() 获取您的String

标签: android retrofit


【解决方案1】:

在回调的尖括号中写入“Response”,然后从该响应中提取流。

service.getToto("toto", new Callback<Response>() {
    @Override
    public void success(Response result, Response response) {

        //Try to get response body
        BufferedReader reader = null;
        StringBuilder sb = new StringBuilder();
        try {

            reader = new BufferedReader(new InputStreamReader(result.getBody().in()));

            String line;

            try {
                while ((line = reader.readLine()) != null) {
                    sb.append(line);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }


        String result = sb.toString();
    }

    @Override
    public void failure(RetrofitError error) {

    }
});

【讨论】:

  • @Kerwan 如果这个答案对你有帮助,请选择这个答案并投票,这样它也可以帮助其他人
  • 好的,谢谢!我忘了我的问题,我改用 Volley,但你的解决方案有效:)
  • 如果我按照你的方法,我得到一个错误:retrofit.RetrofitError: No Retrofit annotation found。 (参数#2)
  • @IgorGanapolsky 试试我的其他答案。可能会帮助你。链接stackoverflow.com/questions/23853552/…
  • @NiteshKhatri 我的主要问题是在 RXJava observable 中指定数据类型和回调。就 RXJava 而言,Retrofit 仅返回一个回调(可观察)。所以我现在只是将 Retrofit Response 作为唯一的返回类型进行内省,问题就消失了。
【解决方案2】:

改造 2.0 之前

   String bodyString = new String(((TypedByteArray) response.getBody()).getBytes());

改造 2.0

 String  bodyString = new String(response.body().bytes());

【讨论】:

  • 这个解决方案很棒,因为我可以有我的响应类型并吃掉它。
  • @shiami 无法解析符号“TypedByteArray”。我在哪里可以上这门课?
  • @anivaler 我认为它不再适用于 Retrofit 2.0+
  • bodyString = new String(response.body().bytes());改造 2.0
  • @Robert 我在尝试这行代码时收到“无法解析方法 'bytes()'”。
【解决方案3】:

如果您在用于创建服务的RestAdapter 上设置.setLogLevel(RestAdapter.LogLevel.FULL),您应该在调试控制台中获得原始 JSON 响应输出。

RestAdapter restAdapter = new RestAdapter.Builder()
    .setServer("http://my_lovely_api.com")
    .setLogLevel(RestAdapter.LogLevel.FULL)
    .build();

mService = restAdapter.create(MyService.class);

如果你想对这个原始响应做一些不同的事情,你仍然可以使用你在成功块中的代码来创建一个 JSON 字符串,假设你在 setLogLevel 方法中保留 LogLevel.FULL,如果没有,那么它不会解析来自 response.getBody().in() 的 InputStream,因为它已被读取并关闭。

【讨论】:

  • 太棒了! .setLogLevel(RestAdapter.LogLevel.FULL) 帮助我
  • 这仅在您的应用程序在 DEBUG 中运行时有用。这是一个很好的解决方案,特别是因为我们不想登录发布版本。不幸的是,我不得不在发布版本中编写日志。因此,此解决方案在这种情况下不起作用。我正在使用改造 1.9
【解决方案4】:

我最近遇到了类似的问题。我想查看响应正文中的一些 json,但不想处理 Retrofit 中的 TypedByteArray。我发现解决它的最快方法是制作一个带有单个字符串字段的 Pojo(普通旧 Java 对象)。更一般地,您会制作一个 Pojo,其中一个字段对应于您想要查看的任何数据。

例如,假设我正在发出一个请求,其中来自服务器的响应是响应正文中名为“access_token”的单个字符串

我的 Pojo 应该是这样的:

public class AccessToken{
    String accessToken;

    public AccessToken() {}

    public String getAccessToken() {
        return accessToken;
    }
} 

然后我的回调看起来像这样

Callback<AccessToken> callback = new Callback<AccessToken>() {
   @Override
   public void success(AccessToken accessToken, Response response) {
       Log.d(TAG,"access token: "+ accessToken.getAccessToken());
   }

   @Override
   public void failure(RetrofitError error) {
       Log.E(TAG,"error: "+ error.toString());
   }
};

这将使您能够查看您在回复中收到的内容。

【讨论】:

    【解决方案5】:

    请不要为此使用流和 straemReaders。 使用像 square 这样的智能解决方案:

    private Response logAndReplaceResponse(String url, Response response, long elapsedTime)
    

    http://www.programcreek.com/java-api-examples/index.php?source_dir=retrofit-jaxrs-master/retrofit/src/main/java/retrofit/RestAdapter.java

    示例:

    private String getResponseBody(Response response) {
        String result = "";
        //Try to get response body
        if (response.getBody() instanceof TypedByteArray) {
            TypedByteArray b = (TypedByteArray) response.getBody();
            result = new String(b.getBytes());
        }
        return result;
    }
    

    【讨论】:

      【解决方案6】:

      另一种解决方案是执行以下操作:

        private static String bodyAsString(RequestBody body) {
          try {
            Buffer buffer = new Buffer();
            body.writeTo(buffer);
            return buffer.readString(body.contentType().charset());
          } catch (IOException e) {
            throw new RuntimeException(e);
          }
        }
      

      取自https://github.com/square/okhttp/blob/master/okcurl/src/test/java/com/squareup/okhttp/curl/MainTest.java#L93-L101

      【讨论】:

        【解决方案7】:

        使用 2.1.0 版本,您可以获取内容为

        public void onResponse(Call<T> call, Response<T> response) {
            String errorString = response.errorBody().string();
        }
        

        【讨论】:

          【解决方案8】:

          就这样吧:

          ModelClass modelclass=response.response.body()
          System.out.println("****************-----retro rsp----1-------"+modelclass.getMessage());
          

          【讨论】:

            【解决方案9】:

            在您的响应模型中按 cmd+n 并覆盖“toString”方法,并且仅调用 response.toString();

            @Override
            public String toString() {
                return "{" +
                        "key_one='" + var_keyone + '\'' +
                        ", key_two='" + var_keytwo + '\'' +
                        '}';
            }
            

            【讨论】:

              猜你喜欢
              • 2017-01-15
              • 2016-03-05
              • 2018-01-29
              • 1970-01-01
              • 2018-11-04
              • 2021-02-09
              • 2018-06-11
              • 2016-10-02
              • 2016-02-18
              相关资源
              最近更新 更多