如何在多线程中取消DefaulHttpClient执行过程

时间:2011-08-10 08:15:12

标签: android multithreading httpclient

我正在开发一个非常依赖互联网的Android应用程序,我经常使用这个RestClient Class检索数据,它包含了使用DefaultHttpClient进行网络请求的一些细节。

我总是使用不同的线程来执行HTTP请求,我创建了一个这样的类:

public class AsyncWorker {

    final String SERVER_URL = "http://api.blabla.com";
    RestClient client = new RestClient();

    public void requestHttp(final String url, final ArrayList<NameValuePair> params, final RequestListener listener) {
        new Thread(new Runnable() {

            public void run() {
                try {
                    client.setUrl(url);
                    client.setParams(params);
                    client.Execute(RestClient.RequestMethod.POST);
                    String response = client.getResponse();
                    listener.onComplete(response);
                } catch (Exception ex) {
                    Log.d("LOGIN", ex.getMessage());
                }
            }
        }).start();
    }
    etc...

因此,每当我需要执行HTTP请求时,我只需要创建AsyncWorker对象,并提供RequestListener回调接口。

但问题是,当用户按后退/取消按钮时,如何取消HTTP请求?在这种情况下,应用程序仍然在一个活动中,例如我创建一个对话框,用户从该对话框中执行请求,然后按下后退按钮,对话框被解除,我需要取消该时间的请求。

4 个答案:

答案 0 :(得分:3)

我遇到了同样的问题,并找到了解决方法。这是我做的:

我使用 CloseableHttpClient 以及其他相关类,而不是默认情况下附带Android的 DefaultHttpClient

这些课程来自https://hc.apache.org/downloads.cgi。或者对于direcet访问:http://apache.mirrors.hoobly.com//httpcomponents/httpclient/binary/httpcomponents-client-4.3.2-bin.tar.gz

这样,在Request对象上调用 abort()方法实际上将停止连接。但是,使用此库不是解决方案;原因是Android已经内置了过时的HTTPCLIENT库,并且上面链接指向的库中的大多数类似乎在运行时都会丢失。

问题是上面的库和内置的org.apache httpclient包中的包都有相同的命名空间,并且只会在编译时使用Android提供的内置org.apache类。

此处可以找到此问题的示例:java.lang.NoSuchFieldError: org.apache.http.message.BasicLineFormatter.INSTANCE

感谢那些提供http://code.google.com/p/httpclientandroidlib/作为选项的人(可在java.lang.NoSuchFieldError: org.apache.http.message.BasicLineFormatter.INSTANCE的答案部分找到)

推荐:实际取消http请求的一个地方可能是在进度对话框的OnCancel Listener中,而不是AyncTask的onCancelled()回调方法。

答案 1 :(得分:1)

您使用的RestClient对象未公开interrupt() DefaultHttpClient的任何client.Execute()方法(这是完成大部分工作的后备对象)。没问题 - DefaultHttpClient似乎没有任何中断或中止功能,无法首先公开。

所以,你的左边有Thread的阻止操作。

你有一个解决方案的一半 - 这是将阻塞操作放入一个线程。你跌倒的地方是你的架构 - 你使用的是一个线程/听众设置,它不会给你很多摆动空间。

尝试将匿名AsyncTask切换为client.Execute()。这不会解决您onProgressUpdate()阻止的问题,但会允许您丢弃侦听器(将其替换为onPostExecute()task.cancel())。

这将允许您拨打{{1}},向任务发出信号,不再需要它。这将允许您重新分配一个新的AsyncTask,孤立已取消的任务,孤立的线程将随着它的能力快速完成并悄然消亡,而其余的应用程序继续使用它所需的内容。

((在不相关的注释中,“Execute()”是一种方法,不应大写))

答案 2 :(得分:0)

使用线程基元。标记running并最初将其设置为true。在while(running)循环中执行REST请求。

onPause()中,将运行标记设置为false

答案 3 :(得分:0)

我建议你看一下ClientConnectionManager界面。这允许您执行诸如释放连接,关闭连接等内容。您可能需要增强RestClient的实现 - 因为您的RestClient不会公开基础DefaultHttpClient对象(您可以使用ClientConnectionManager方法从中获取getClientConnectionManager()。)