即使设置了超时参数,HttpClient也会长时间停顿

时间:2011-08-17 01:37:17

标签: java android httpclient

我有一个应用程序正在从远程服务下载缩略图和其他资源。

我正在使用DefaultHttpClient的单个实例和我编写的自定义类来安排我的所有下载。所有下载都是通过AsyncTask在后台线程上串行运行的。在onPostExecute在AsyncTask中执行之前,我不会重新运行我的下载例程。

这通常很有效。如果我排队20张图片,我的调度程序就可以了。但是,我遇到的情况是程序只是在调用client.execute(其中client是我的DefaultHttpClient实例)时停止。我可以通过浏览应用程序并执行随机操作(滚动列表,在活动之间来回导航等)来莫名其妙地复苏该过程。 就好像我正在做的事情是向一个已经停滞或死锁的线程发送“唤醒”消息。

我在应用程序的所有移动部分添加了一个令人讨厌的日志记录,以查看此过程外部的某些内容是否导致某种死锁情况。我通过pid查看LogCat,看看在我的进程中是否还有其他任何事情发生在停止或恢复的时候,我没有看到任何与众不同的东西。关于这一点最奇怪的部分是我可以一遍又一遍地复制确切的条件。

FWIW,我已经在HttpClient实例和我传递给execute方法的HttpGet实例上设置了套接字超时和连接超时。这不会导致execute方法提前返回或抛出异常或类似的东西。当程序“重新开始”时,HttpClient.execute返回一个有效的HttpResponse,一切正常。

我可以调试的任何想法,以找出它被绊倒的地方?我知道这是一个非常具体的条件,但是否有任何高级方法可以在Android中专门调试DefaultHttpClient或http流量?

谢谢!

2 个答案:

答案 0 :(得分:5)

你是否跨线程共享相同的HttpClient?默认情况下它不是线程安全的,因此您可能需要检查它。很可能它在I / O上阻塞了,所以你应该做一些线程调试。您可以使用类似的方法来启用HttpClient线路转储日志:

Logger.getLogger("org.apache.http.wire").setLevel(Level.FINEST);
Logger.getLogger("org.apache.http.headers").setLevel(FINEST);
Logger.getLogger("httpclient.wire.header").setLevel(FINEST);
Logger.getLogger("httpclient.wire.content").setLevel(FINEST);

System.setProperty("org.apache.commons.logging.Log",
     "org.apache.commons.logging.impl.SimpleLog");
System.setProperty("org.apache.commons.logging.simplelog.showdatetime", "true");
System.setProperty("org.apache.commons.logging.simplelog.log.httpclient.wire", "debug");
System.setProperty("org.apache.commons.logging.simplelog.log.org.apache.http", "debug");
System.setProperty("org.apache.commons.logging.simplelog.log.org.apache.http.headers", "debug");

要启用它,请执行以下shell命令。 Wire日志将输出到logcat:

adb shell setprop log.tag.org.apache.http VERBOSE 
adb shell setprop log.tag.org.apache.http.wire VERBOSE 
adb shell setprop log.tag.org.apache.http.headers VERBOSE

答案 1 :(得分:-2)

我之前遇到过类似的问题。 当我尝试将HTTP加入队列时,方法httpClient.execute(get);将不会返回响应,例如死锁。

HttpResponse response = httpClient.execute(get);
HttpEntity entity = response.getEntity();

这是我的代码,我所做的就是调用entity.consumeContent();然后它就可以了。