当doInBackground调用另一个单独类的方法时,如何取消异步任务

时间:2014-12-03 14:15:18

标签: android android-asynctask

我正在从异步任务的doInBackground调用另一个类的方法。 现在我需要在调用cancel时停止下载。我不知道在哪里检查isCancelled()的值。

class myasync extends Asynctask{
    protected String doInBackground(String... sURL) {
        abc = new abc();
        abc.getURLResult(sURL[0])
    }
}

class abc()
{    
    getURLResult(String URL)
    {
        for(int i=0; i<fp.size(); i++){
            //some text to download
        }
    }
}

class myclass
{
    myclass()
    {
        myasync = new myasync();
        myasync.execute("http:\\");
    }

    stopDownload()
    {
        myasync.cancel(true);
    }
}

编辑: 通过结合以下两个答案使用了以下解决方案:

1. myclass.cancel1(true);

 class myclass
    {
        myclass()
        {
            myasync = new myasync();
            myasync.execute("http:\\");
        }

        stopDownload()
        {
            myasync.cancel1(true);
        }
    }

  2. 
 class myasync extends Asynctask{
        protected String doInBackground(String... sURL) {
            abc = new abc();
            abc.getURLResult(sURL[0])
        }

        cancel1()
        {
         abc.cancel();
         }
    }


3. 
       class abc()
    {    
        private boolean cancel = false;
        getURLResult(String URL)
        {
            for(int i=0; i<fp.size(); i++){
                //some text to download
                 if(cancel)
                    break;
            }
        }

             cancel()
             {
               cancel = true;
              }
    }

上述方法正在运行。但是,方法myclass.stopDownload()正在UI线程中运行,因此myasync.cancel1()abc.cancel()正在运行UI线程。并且myAsync.doInBackground()abc.getURLResult()正在单独运行。我不太了解进程间通信。我希望这是正确的事情。

2 个答案:

答案 0 :(得分:0)

不是很好,但你可以通过添加一个静态变量isDownloading来做这样的事情:

protected String doInBackground(String... sURL) {
abc = new abc();
abc.getURLResult(sURL[0])
}
}

class abc()
{

getURLResult(String URL)
{

 for(int i=0; i<fp.size(); i++){
     if(!myclass.isDownloading){ //ADDED
         break; // or Return or handle Cancel
     }
//some text to dopwnload
}

}

class myclass
{

public static boolean isDownloading; // ADDED

myclass()
{
myasync = new myasync();
isDownloading = true; // ADDED
myasync.execute("http:\\");
}
   stopDownload()
   {
    isDownloading = false; // ADDED
    myclass.cancel(true);
    }
}

答案 1 :(得分:0)

<强>更新

从AsyncTask取消doc。我们必须检查异步任务是否被取消了。

  

调用此方法将导致调用onCancelled(Object)   在doInBackground(Object [])返回后的UI线程上。打电话给这个   方法保证永远不会调用onPostExecute(Object)。后   调用此方法时,应检查返回的值   isCancelled()定期从doInBackground(Object [])来完成   尽早完成任务。

为此,请将asyncTask本身作为参数与URL一起发送到getURLResult:

protected String doInBackground(String... sURL) {
    new abc().getURLResult("http://...", this); // this here is the asyncTask itself.
}

getURLResult(String URL, myasync myAsyncTask)
{
    for(int i=0; i<fp.size(); i++){
        if(myAsyncTask.isCancelled()){
            break;
        }
    }
}

不要像其他建议那样使用布尔值。它根本不安全,因为可以启动另一个AsyncTask。它是一个后台线程。你不能保证哪个会首先检查布尔值。可以取消所有AsyncTasks。

旧帖子:

您需要检查取消以确保取消的唯一地方!在onPostExecute上。您无法保证在调用cancel方法时取消了异步任务。因此,您需要检查客户端应用程序是否要求取消它,并且不再需要返回的数据。

private boolean askedForCancellation = true;

@Override
protected void onPostExecute(Object response) {
    if (!askedForCancellation)
       // parse response
    else
       // ignore. or send message to activity to stop loading if you didn't already did that when called cancel method.
}

要实现这一点,请将以下取消方法添加到 AsyncTask

public final boolean cancel(boolean mayInterruptIfRunning) {
    askedForCancellation = true;
    return mFuture.cancel(mayInterruptIfRunning);
}

在你班上:

myasync.cancel(true);
myasync = null;

将myasync设置为null即可。因为,你不能再使用它再次执行。你会得到一个运行时错误。你需要重新初始化它。

  

检查AsyncTask是否要求取消。检查是否值   myasync等于null。记得AsyncTask要求得到的   取消,但没有取消,因为无法保证   打电话取消时取消。你做的是忽略了   对onPostExecute

的回复

到目前为止,我在超过15个应用程序中使用了这种方法。没有错误,没有意外的行为。