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

发布于 2024-11-28 16:59:57 字数 1221 浏览 1 评论 0原文

我正在开发一个非常依赖互联网的Android应用程序,我经常使用这个RestClient类检索数据,它包装了一些有关使用 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请求呢?在这种情况下,应用程序仍然处于一个活动中,例如我创建一个对话框,用户从该对话框中发出请求,然后按下后退按钮,对话框消失,我需要当时取消该请求。

I am developing an android application that rely very much on internet, I retrieve data frequently using this RestClient Class, that wrap some detail on using DefaultHttpClient to do network request.

And I always use different thread to do the HTTP request, I create a class like this:

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...

So whenever I need to do a HTTP request, I only need to create AsyncWorker object, and provide the RequestListener callback interface.

But the problem is, how can I cancel the HTTP Request when the user press the back/cancel button? and in this case the application still is in one activity, for example I create a dialog, and the user do a request from that dialog, and then back button pressed, the dialog dismissed, and I need to cancel the request on that time.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

梦回梦里 2024-12-05 16:59:57

我遇到了同样的问题并且能够找到解决方案。以下是我所做的:

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

这些类来自 https://hc.apache.org/downloads.cgi。或者直接访问: 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。实例

建议:实际取消 http 请求的一个位置可以在进度对话框的 OnCancel 侦听器中,而不是在AyncTask 的 onCancelled() 回调方法。

I had the same issue and was able to find a fix. Here is what I did:

I used CloseableHttpClient along with other related classes, instead of the DefaultHttpClient that by default comes with Android.

These classes are from https://hc.apache.org/downloads.cgi. OR for direcet access: http://apache.mirrors.hoobly.com//httpcomponents/httpclient/binary/httpcomponents-client-4.3.2-bin.tar.gz

With this, calling the abort() method on the Request object will actually halt the connection. However, using this library is not the solution; reason being that Android already has the outdated HTTPCLIENT library inbuilt, and most classes in the library pointed to by the above link would appear to be missing at runtime.

The problem is that both the packages in the above library and the inbuilt org.apache httpclient package have same namespace, and would result in the use of only the inbuilt org.apache classes provided by Android at compilation.

An example of this issue is found here: java.lang.NoSuchFieldError: org.apache.http.message.BasicLineFormatter.INSTANCE.

Thanks to the guys who provided http://code.google.com/p/httpclientandroidlib/ as an option (found in the answer section of java.lang.NoSuchFieldError: org.apache.http.message.BasicLineFormatter.INSTANCE)

Recommendation: one place to actually cancel an http request could be within OnCancel Listener of a progress dialog, instead of the AyncTask's onCancelled() callback method.

春花秋月 2024-12-05 16:59:57

您使用的 RestClient 对象不会公开 DefaultHttpClient 的任何 interrupt() 方法(这是完成大部分工作的支持对象)。不是问题 - DefaultHttpClient 似乎没有任何中断或中止功能可以首先公开。

因此,您在 client.Execute() 上留下了阻塞操作。

找到解决方案的一半方法 - 即将阻塞操作放入线程中。你的失败之处在于你的架构——你使用的线程/监听器设置并没有给你太多的回旋余地。

尝试将匿名 Thread 切换为 AsyncTask。这不会解决 client.Execute() 阻塞的问题,但允许您丢弃侦听器(用 onProgressUpdate() 或 <代码>onPostExecute())。

这将允许您调用 task.cancel(),向任务发出不再需要的信号。这将允许您重新分配一个新的 AsyncTask,孤立已取消的任务,然后孤立的线程将尽快完成并安静地死亡,而应用程序的其余部分则继续执行其需要的操作。

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

The RestClient object your using doesn't expose any interrupt() method of DefaultHttpClient (which is the backing object doing most of the work). Not a problem - the DefaultHttpClient doesn't seem to have any interrupt or abort functionality to expose in the first place.

So, your left with a blocking operation on client.Execute().

Your half way to having a solution - which is to put the blocking operation into a Thread. Where your falling down is your architecture - your using a Thread/Listener setup which doesn't give you alot of wiggle room.

Try switching your anonymous Thread to an AsyncTask. This won't solve the problem of you're client.Execute() from blocking but will allow you to throw away the listener (replacing it with onProgressUpdate() or onPostExecute()).

What this will do is allow you call task.cancel(), signalling to the Task it is no longer needed. This will allow you to reassign a new AsyncTask, orphaning the cancelled task, the orphaned thread will then finish quickly as its able and die quietly while the rest of your application gets on with what it needs to.

((On an unrelated note, "Execute()" is a method and shouldn't be capitalised))

一人独醉 2024-12-05 16:59:57

我建议您看一下 ClientConnectionManager 界面。这允许您执行释放连接、关闭连接等操作。不过,您可能需要增强 RestClient 的实现 - 因为您的 RestClient 不会公开底层DefaultHttpClient 对象(您可以使用 getClientConnectionManager() 方法从该对象获取 ClientConnectionManager)。

I suggest you take a look at the ClientConnectionManager interface. This allows you to do stuff like releasing a connection, shutting down a connection etc. You may need to enhance the implementation of RestClient though - since your RestClient does not expose the underlying DefaultHttpClient object (from which you can get to the ClientConnectionManager using the getClientConnectionManager() method).

神经大条 2024-12-05 16:59:57

使用线程原语。有一个标志 running 并最初将其设置为 true。在 while(running) 循环中执行 REST 请求。

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

Use the threading primitives. Have a flag running and set it to true initially. Do your REST requests in a while(running) loop.

In your onPause(), set the running flag to false.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文