【问题标题】:Android HTTP Client freezesAndroid HTTP 客户端冻结
【发布时间】:2012-04-17 21:55:16
【问题描述】:

我在我的 HTTP 请求中遇到了一些奇怪的行为。我有一些用户说这个调用永远不会回来(标记它是异步调用的微调器永远不会消失)。我以前见过这种情况,但我将其归因于通过 Charles Proxy 的模拟器。直到现在我还没有在实际手机上看到它。

我不确定什么会导致这种情况发生,这就是我在此处发布它的原因。这是调用,使用 Jackson 将结果反序列化为值对象。我看到模拟器冻结的两个地方是 httpclient.execute(httpGet);和 getObjectMapper().readValue(jp, SyncVO.class);.

在调试时,单步执行有问题的语句会导致调试器永远无法控制单步执行。同时,我看到请求通过 Charles 从服务器发出并返回。只是应用似乎没有得到响应,只是坐在那里。

所以,这里是代码。感谢您的帮助!

public SyncVO sync(String userId, long lastUpdate, boolean includeFetch) throws IOException {
    SyncVO result = null;

    String url = BASE_URL + "users/" + userId + "/sync" + "?" + "fetch=" + includeFetch;

    if (lastUpdate > 0) {
        url += "&updatedSince=" + lastUpdate;
    }

    DefaultHttpClient httpclient = new DefaultHttpClient();
    HttpGet httpGet = new HttpGet(url);

    httpGet.setHeader("Accept", "application/json");
    httpGet.setHeader("Accept-Encoding", "gzip");
    httpGet.setHeader(AUTHORIZATION, BEARER + " " + mOAuthToken);
    httpclient.getParams().setParameter(CoreProtocolPNames.USER_AGENT, USER_AGENT_STRING);
    httpclient.getParams().setBooleanParameter(CoreProtocolPNames.USE_EXPECT_CONTINUE, false);

    HttpResponse response = httpclient.execute(httpGet);

    if (isUnauthorized(response)) {
        APPLICATION.needReauthentication();
        return null;
    }

    if (response != null) {
        InputStream stream = response.getEntity().getContent();
        Header contentEncoding = response.getFirstHeader("Content-Encoding");
        if (contentEncoding != null && contentEncoding.getValue().equalsIgnoreCase("gzip")) {
            stream = new GZIPInputStream(stream);
        }

        InputStreamReader inReader = new InputStreamReader(stream, "UTF-8");
        JsonParser jp = mJsonFactory.createJsonParser(inReader);
        result = getObjectMapper().readValue(jp, SyncVO.class);
    }   

    return result;
}

private ObjectMapper getObjectMapper() {
    return (new ObjectMapper()
        .configure(Feature.AUTO_DETECT_FIELDS, true)
        .configure(Feature.FAIL_ON_UNKNOWN_PROPERTIES, false)
        .configure(JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true));
}

【问题讨论】:

  • 我们通常会在初始化 DefaultHttpClient 时指定超时时间,以避免应用程序永远等待服务器响应。
  • 我编辑了我的帖子,以澄清我实际上看到请求发出并返回是因为查尔斯,但应用程序没有做任何事情!
  • 是否有任何单例类被调用并为它设置了监听器,这些监听器也被从其他地方调用?或者您的微调器是否在某个回调函数中被解除?

标签: android http httpclient httprequest


【解决方案1】:

不要忘记在每次请求后使用实体内容。

HttpEntity entity = response.getEntity();
  try {
   if (entity != null)
    entity.consumeContent();
  } catch (IOException e) {
   e.printStackTrace();
  }

【讨论】:

【解决方案2】:

您绝对应该使用连接超时和套接字读取,并为服务器最坏的情况做好准备。网络操作永远不会 100% 可预测,您的客户也无能为力,因此请确保您以最佳方式编写代码。

httpParameters = httpclient.getParams();
HttpConnectionParams.setConnectionTimeout(httpParameters, 5000);
HttpConnectionParams.setSoTimeout(httpParameters, 10000);

您也可以使用 asyncTask.cancel(true); 取消任务

【讨论】:

    【解决方案3】:

    原因是因为您打开了stream。因此,response 处于不确定状态。这意味着您的全局变量 httpClient 也处于不确定状态,并且在重用客户端时无法获取新实体。

    您应该在完成直播后致电close()

    stream.close();
    

    【讨论】:

      【解决方案4】:

      网络调用需要一段时间并且会阻塞 UI 线程。与您的杰克逊反序列化代码相同。这些东西需要放在一个单独的线程上。请参阅AsyncTask 了解简单的方法。

      【讨论】:

      • 是的,它是从 AsyncTask 调用的。问题是代码有时永远不会超过 .execute 或 .readValue
      猜你喜欢
      • 2014-08-10
      • 2013-01-14
      • 1970-01-01
      • 2013-12-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多