【问题标题】:Android KitKat HttpURLConnection disconnect AsyncTaskAndroid KitKat HttpURLConnection 断开 AsyncTask
【发布时间】:2013-12-04 22:41:08
【问题描述】:

在我的应用程序中,我在AsyncTask 中使用HttpURLConnection 下载文件。如果文件下载时间过长,那么我想取消它;我通过关闭流并在HttpURLConnection 对象上调用disconnect() 来做到这一点。多年来,该代码在 Android 中完美运行。然而,既然 KitKat 出来了,问题就出现了。具体来说,disconnect() 调用本身需要几秒钟或更长时间才能完成。在 KitKat 之前的设备中,它需要一毫秒或更短的时间。真正奇怪的是,当我在单独的线程上执行断开调用时,它又真的很快了。所以在AsyncTaskdoInBackground方法中调用它一定是个问题。需要注意的一件事是我的AsyncTask 确实有一个Looper.prepare() 电话。

有谁知道 KitKat 和其他 Android 版本的区别是什么?我梳理了更改列表,没有看到与此问题相关的任何内容。

【问题讨论】:

  • 遇到同样的问题
  • 我看到了类似的问题;我做了一些调查,这是关闭流的方式发生了变化。我已经详细介绍了here - 不幸的是我还没有修复。
  • 同样的结果,在单独的线程上断开连接也会给我​​带来同样的延迟。

标签: android android-asynctask httpurlconnection android-4.4-kitkat


【解决方案1】:

Kitkat 似乎使用了 okhttp 而不是之前的 HTTPConnection 实现,或者至少在官方更新的 Nexus 设备上是这样的。

【讨论】:

  • 您是如何确定这一点的?我查看了源码,发现okhttp库已经在源码since 4.2中了。
  • android.googlesource.com/platform/external/okhttp/+log2231db3 中实现的更改在Android 4.3 中不存在(不管标签上说什么);它们确实存在于 Android 4.4 中。
  • 啊,好吧。我仍然很好奇为什么 AsyncTask 中的行为与单独线程中的行为不同。
【解决方案2】:

这可能与persistent connections有关,并且HttpURLConnection试图重用相同的HTTP连接,因此在关闭连接或InputStream时,它试图通过读取并丢弃它们来消耗所有剩余的数据。然后相同的 HTTP 连接就可以为下一个命令做好准备了。

KitKat 中似乎有一些新的实现使事情变得不同并导致问题。

我尝试通过 HTTP 流式传输视频数据,偶尔搜索会导致关闭连接并启动新连接。当然,在这种情况下,我不需要一直提取视频流。

我试着打电话

HttpURLConnection con;
con.setRequestProperty("Connection", "close");

但这并没有什么不同。

但是,我尝试使用与 DefaultHttpClient 相同的代码并调用

HttpGet get = new HttpGet(uri);
get.addHeader("Connection", "close");

然后最终关闭连接的 InputStream 很快,我在调试器中通过进入 ConnectionReuseStrategy.keepAlive 并看到服务器返回 Connection:close 和 DefaultHttpClient 并没有尝试重用连接和读取直到结束来证明这一点。

因此您可以使用 DefaultHttpClient 或找到一种方法使 HttpURLConnection 仅关闭连接而无需读取休息。

【讨论】:

    【解决方案3】:

    你为什么不尝试使用 apache lib http 连接

    类似这样的东西,在你的异步任务中

        HttpClient httpclient = new DefaultHttpClient();
        HttpPost httppost = new HttpPost("http://server.com");
        HttpResponse response = httpclient.execute(httppost);
        if(response!=null)
        {
            final  String responseBody =EntityUtils.toString(response.getEntity());
            if (responseBody != null) 
            {  
    
    
    
            }
    
        }
    

    【讨论】:

    • 这在几年前被默默地弃用了,谷歌建议使用 HttpURLConnection。看到这个blog post
    • 我知道有几个用于 Android 的最新 Apache 东西的端口,但我觉得原始的 Java 东西应该可以工作。
    • 嗨,克里斯,谢谢你的信息,我知道,谷歌不支持它,虽然效果很好,但通常我更喜欢使用 apache 库,因为它比标准的 java http 连接更快。也不需要 while readline 编码部分。网页直接作为字符串返回。就我而言,它效果很好,我强烈推荐它。
    • 我测试过,使用 HttpClient 并关闭响应的 InputStream 会在我的设备上产生同样长的延迟(15 秒)。 borg666:正确格式化您的代码示例!
    • @PointerNull,我们这里不接单,下次一定要好心问,你不在酒吧。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-15
    相关资源
    最近更新 更多