Android HTTP客户端冻结

Android HTTP客户端冻结,android,http,httpclient,httprequest,Android,Http,Httpclient,Httprequest,我在HTTP请求中遇到一些奇怪的行为。我有一些用户说这个调用永远不会回来(标记为异步调用的微调器永远不会消失)。我以前见过这种情况,但我将其归因于通过Charles代理的模拟器。到现在为止,我还没有在手机上看到它 我不确定是什么原因导致了这种情况,这就是为什么我在这里发布它。下面是调用,使用Jackson将结果反序列化为值对象。我看到仿真器冻结的两个点是httpclient.execute(httpGet);和getObjectMapper().readValue(jp,SyncVO.class

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

我不确定是什么原因导致了这种情况,这就是为什么我在这里发布它。下面是调用,使用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));
}

网络调用需要一段时间,将阻塞UI线程。与您的jackson反序列化代码相同。这些东西需要放在一个单独的线程上。请参阅,以获得一种简单的方法。

您一定要使用连接超时和套接字读取,并为服务器的最坏情况做好准备。网络操作永远不会是100%可预测的,而且您的客户机也做不到什么,因此请确保以最佳方式编写代码

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

您还可以使用asyncTask取消任务。取消(true)

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

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

原因是您将
流保持打开状态。因此,
响应
处于不确定状态。这意味着您的全局变量
httpClient
也处于悬而未决的状态,在重新使用客户端时无法获取新实体

处理完流后,应该调用
close()

stream.close();

是的,它是从异步任务调用的。问题是,代码有时永远无法通过.execute或.readvalues。我们通常在初始化DefaultHttpClient时指定超时,以避免应用程序永远等待服务器响应。我编辑了我的帖子,以澄清我确实看到请求因为Charles而发出和返回,但应用程序没有做任何事情!是否有任何正在调用的单例类以及为其设置的侦听器也正在从其他地方调用?或者您的微调器在某个回调函数中被取消了?对同一问题的回答更为全面: