我一直在搜索这个,但我没有找到我的具体问题。我了解AskyncTask
可以使用.cancel(true)
取消,但只有在我有一个循环可以检查值isCanceled()
时才会取消。
但我的问题是..当用户按下时,如何取消AsyncTask
(卡在httpclient.execute()
中)?如果用户导航远离该Activity并转到另一个我不希望运行不受控制的AsyncTask数量,因为这可能导致内存问题,用户可以来回导航并创建不确定数量的任务。这就是为什么我要关闭它们。有人知道吗?我发布了用于连接的代码:
public class Test extends Activity {
@Override
protected void onStart() {
super.onStart();
new ConnectionTask().execute("https://www.mywebserver.com/webservice.php?param1=test");
}
private class ConnectionTask extends AsyncTask<String, Void, String>{
@Override
protected String doInBackground(String... params) {
try {
HttpClient httpclient = DefaultHttpClient(params,clientConnectionManager);
HttpPost httpPost = new HttpPost(params[0]);
HttpResponse httpResponse = httpClient.execute(httpPost);
HttpEntity httpEntity = httpResponse.getEntity();
if(httpEntity != null)
return EntityUtils.toString(httpEntity);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
}
你知道我应该在onStop()中添加什么来取消正在进行的httpClient.execute()函数吗?有时几乎永远陷入困境。
我非常感谢你的帮助,非常感谢你。
如果我关闭ConnectionManager
我必须再次为https进行握手,对吧?创建httpClient
时查看此代码,我将其用于https:
HttpClient httpclient = DefaultHttpClient(params,clientConnectionManager);
感谢大家的快速回复以及此处公开的各种解决方案。我将尝试使用超时(不必等待太多)+ cancel()
函数以避免处理onPostExecute
。我会告诉结果是否符合预期!非常感谢大家!
答案 0 :(得分:4)
根据HttpClient docs,使用HttpUriRequest#abort()
中止请求
1.4。中止请求
在某些情况下,由于目标服务器上的高负载或客户端发出的并发请求太多,HTTP请求执行无法在预期的时间范围内完成。在这种情况下,可能需要提前终止请求并解除阻塞I / O操作中阻止的执行线程。通过调用HttpUriRequest#abort()方法,可以在执行的任何阶段中止由HttpClient执行的HTTP请求。此方法是线程安全的,可以从任何线程调用。当HTTP请求被中止时,它的执行线程 - 即使当前在I / O操作中被阻塞 - 也可以通过抛出InterruptedIOException来解除阻塞
答案 1 :(得分:1)
cancel()
课程中有AsyncTask
个方法。维护一个成员asynctask并在onDestroy().
中取消它然后将该成员设置为null。
使用ClientConnectionManager
关闭连接。
http://developer.android.com/reference/org/apache/http/conn/ClientConnectionManager.html
选中此链接以设置连接的超时。
答案 2 :(得分:1)
我的理解是httpClient.execute()
正在阻止,因此没有代码运行来检查isCancelled()
的值。而且您不希望关闭Connection Manager。
这可能有点hacky,但是代替任何更好的解决方案,如果在Thread.interrupt()
阻止时在线程上调用httpClient.execute()
会发生什么?
快速测试可以验证这一点,只需在Thread
定义中添加ConnectionTask
类型的私有实例变量,将其设置为Thread.currentThread()
顶部的doBackground()
,然后添加一个在其上调用.interrupt()
的公共方法。
如果你很幸运会导致httpClient.execute()
立即退出,抛出异常。在方法调用结束并且AsyncTask
自然结束之前,您可以捕获并执行所需的任何修改。
答案 3 :(得分:0)
您可以覆盖
onPause()
活动方法并在那里写停止连接代码。如果该选项特定于后退按钮,则可以覆盖
onBackButtonPressed()
方法停止执行。
答案 4 :(得分:0)
在onPause()
或onBackButtonPressed()
中,为您的任务致电cancel()
。在doInBackground()
之后
HttpResponse httpResponse = httpClient.execute(httpPost);
检查isCanceled()
并立即返回,如果为true。
当然,您仍然有运行多个任务的风险,但由于此操作是由UI驱动的(即由用户交互启动的任务),因此应该最多只有几个同时运行,前提是超时关于HttpClient是合理的。
更新
一旦确定需要取消任务,您也可以关闭连接管理器。 see docs
应关闭套接字并立即从execute()
返回。创建DefaultHttpClient
时会设置连接管理器。
答案 5 :(得分:0)
对于我在这种情况下常常解决的问题,有一个快速的解决方案。这可能不是正确的方法,因为当您按下应用程序时会立即响应,但在后台网络操作将继续(直到超时,如果您设置)而不阻止应用程序: -
新服务中的所有网络操作都说NSERV。使NSERV扩展Thread类并在run方法中执行所有网络操作。为了使代码更清晰,最好使启动NSERV的活动/服务也扩展Thread类并从其run方法启动NSERV。
然后使用静态字段或单例来访问NSERV中活动/服务中的变量。
EX:
public class NSERV extends Service implements Runnable{
public int onStartCommand (Intent intent, int flags, int startId)
{
Thread t = new Thread (this, "abc");
t.start();
return super.onStartCommand(intent, flags, startId);
}
public void run()
{
//NETWORK OPERATION...
onDestroy();
}
public void onDestroy()
{
stopSelf();
super.onDestroy();
}
}