2012-04-17 97 views
2

我的HTTP请求中遇到了一些奇怪的行为。我有一些用户说这个调用不会回来(微调者称它是异步调用永远不会消失)。我之前看到过这种情况,但我把它归功于通过Charles Proxy的模拟器。直到现在,我还没有在实际电话中看到它。Android HTTP客户端死机

我不确定这会发生什么,这就是为什么我在这里发布它。接下来是调用,使用Jackson将结果反序列化为一个Value Object。看到模拟器冻结的两个点是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)); 
} 
+0

我们通常在初始化DefaultHttpClient时指定超时,以避免应用程序永远等待服务器响应。 – yorkw 2012-04-17 22:12:40

+0

我编辑了我的帖子,以澄清我实际上看到请求出去并回来,因为查尔斯,但该应用程序不会做一件事! – Chewie 2012-04-18 00:22:48

+0

是否有任何单例类被调用,为它设置的监听器也是从其他地方调用的?或者是你的微调在某些回调函数中被解雇了? – Shubhayu 2012-04-18 01:32:53

回答

-1

网络调用需要一段时间,会阻塞UI线程。和你的杰克逊反序列码一样。这东西需要放在一个单独的线程。见AsyncTask一个简单的方法来做到这一点。

+0

是的,它是从AsyncTask调用的。问题是,代码有时永远不会超过.execute或.readValue – Chewie 2012-04-17 22:10:24

1

你应该明确地使用连接超时和套接字读取,并准备好从服务器的最坏情况。网络运营永远不可能100%可预测,客户可以做的事情不多,所以要确保代码优化。

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

也可以取消与asyncTask.cancel(真)的任务;

4

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

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

更充分充实回答相同的问题:http://stackoverflow.com/a/14088063 – blahdiblah 2016-04-01 01:32:05

1

的原因是因为你已经离开stream开放。因此,response被搁置。这意味着您的全局变量httpClient也处于无用状态,并且在重新使用客户端时无法获得新实体。

在完成流后,您应该致电close()

stream.close();