我正在开发一个非常依赖互联网的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请求?在这种情况下,应用程序仍然在一个活动中,例如我创建一个对话框,用户从该对话框中执行请求,然后按下后退按钮,对话框被解除,我需要取消该时间的请求。
答案 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()
。)