2012-04-17 148 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();