用户按下时取消正在进行的连接

时间:2011-09-12 16:51:58

标签: java android

我一直在搜索这个,但我没有找到我的具体问题。我了解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。我会告诉结果是否符合预期!非常感谢大家!

6 个答案:

答案 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

选中此链接以设置连接的超时。

How to set HttpResponse timeout for Android in Java

答案 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();
}
}