Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/visual-studio-2012/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 取消正在执行的异步任务的理想方法_Android_Android Asynctask - Fatal编程技术网

Android 取消正在执行的异步任务的理想方法

Android 取消正在执行的异步任务的理想方法,android,android-asynctask,Android,Android Asynctask,我正在后台线程中使用AsyncTask运行远程音频文件获取和音频文件播放操作。当提取操作运行时,将显示一个可取消的进度条 当用户取消(决定不执行)操作时,我想取消/中止运行的AsyncTask。处理这种情况的理想方法是什么?简单:不要使用异步任务AsyncTask设计用于快速结束(数十秒)的短操作,因此无需取消。“音频文件播放”不合格。普通音频文件播放甚至不需要后台线程。刚刚发现AlertDialogs的布尔取消(…)我一直在到处使用,实际上什么都没用。太好了。 所以 公共类MyTask扩展了A

我正在后台线程中使用
AsyncTask
运行远程音频文件获取和音频文件播放操作。当提取操作运行时,将显示一个
可取消的
进度条


当用户取消(决定不执行)操作时,我想取消/中止运行的
AsyncTask
。处理这种情况的理想方法是什么?

简单:不要使用
异步任务
AsyncTask
设计用于快速结束(数十秒)的短操作,因此无需取消。“音频文件播放”不合格。普通音频文件播放甚至不需要后台线程。

刚刚发现
AlertDialogs
布尔取消(…)我一直在到处使用,实际上什么都没用。太好了。
所以

公共类MyTask扩展了AsyncTask{
private volatile boolean running=true;
私人最终进度对话;
公共MyTask(上下文ctx){
progressDialog=gimmeOne(ctx);
progressDialog.setCancelable(真);
progressDialog.setOnCancelListener(新的OnCancelListener(){
@凌驾
public void onCancel(对话框接口对话框){
//实际上可以设置running=false;就在这里,但我会
//坚持合同。
取消(真);
}
});
}
@凌驾
受保护的void onPreExecute(){
progressDialog.show();
}
@凌驾
受保护的void onCancelled(){
运行=错误;
}
@凌驾
受保护的Void doInBackground(Void…参数){
(跑步时){
//这项工作很辛苦吗
}
返回null;
}
// ...
}

执行此操作的唯一方法是检查isCancelled()方法的值,并在返回true时停止播放。

这就是我编写AsyncTask的方式
关键是添加线程。睡眠(1)


问题是AsyncTask.cancel()调用只调用任务中的onCancel函数。这是您要处理取消请求的位置

下面是我用来触发更新方法的一个小任务

private class UpdateTask extends AsyncTask<Void, Void, Void> {

        private boolean running = true;

        @Override
        protected void onCancelled() {
            running = false;
        }

        @Override
        protected void onProgressUpdate(Void... values) {
            super.onProgressUpdate(values);
            onUpdate();
        }

        @Override
        protected Void doInBackground(Void... params) {
             while(running) {
                 publishProgress();
             }
             return null;
        }
     }
私有类UpdateTask扩展异步任务{
私有布尔运行=真;
@凌驾
受保护的void onCancelled(){
运行=错误;
}
@凌驾
受保护的void onProgressUpdate(void…值){
super.onProgressUpdate(值);
onUpdate();
}
@凌驾
受保护的Void doInBackground(Void…参数){
(跑步时){
出版进度();
}
返回null;
}
}

如果您正在进行计算

  • 您必须定期检查
    isCancelled()
如果您正在执行HTTP请求

  • HttpGet
    HttpPost
    的实例保存到某个地方(例如公共字段)
  • 调用
    cancel
    后,调用
    request.abort()
    。这将导致
    IOException
    被抛出到
    doInBackground

在我的例子中,我有一个连接器类,用于各种异步任务。为了简单起见,我向该类添加了一个新的
abortAllRequests
方法,并在调用我们的全局AsyncTask类变量
cancel
后直接调用了该方法

LongOperation LongOperationOdeme = new LongOperation();
以及中断异步任务的键控返回操作

   @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            LongOperationOdeme.cancel(true);
        }
        return super.onKeyDown(keyCode, event);
    }

这对我来说很有用。

我不喜欢用
取消(true)
强制中断异步任务,因为它们可能需要释放资源,例如关闭套接字或文件流,将数据写入本地数据库等。另一方面,我曾经遇到过异步任务在部分时间内拒绝自己完成的情况,例如,有时主活动正在关闭,我请求异步任务从活动的
onPause()
方法内部完成。因此,这不是简单地调用
running=false
的问题。我必须选择一种混合解决方案:两者都调用
running=false
,然后给异步任务几毫秒的时间来完成,然后调用
cancel(false)
cancel(true)


因此,在
doInBackground()
完成后,有时调用
onCancelled()
方法,有时调用
onPostExecute()
。但至少异步任务的终止是有保证的。

参考Yanchenko在10年4月29日的回答: 当“doInBackground”下的代码在异步任务的每次执行过程中都必须执行多次时,使用“while(running)”方法是很好的。如果每次执行异步任务时只需执行一次“doInBackground”下的代码,则将“doInBackground”下的所有代码包装在“while(running)”循环中不会在异步任务本身取消时停止后台代码(后台线程)的运行,因为“while(running)”循环'条件将仅在while循环中的所有代码至少执行一次后进行计算。你也应该这样做 (a.)将“doInBackground”下的代码分解为多个“while(running)”块或 (b.)在“doInBackground”代码中执行大量“isCancelled”检查,如中的“取消任务”部分所述

因此,对于选项(a),可以修改Yanchenko的回答如下:

public class MyTask extends AsyncTask<Void, Void, Void> {

private volatile boolean running = true;

//...

@Override
protected void onCancelled() {
    running = false;
}

@Override
protected Void doInBackground(Void... params) {

    // does the hard work

    while (running) {
        // part 1 of the hard work
    }

    while (running) {
        // part 2 of the hard work
    }

    // ...

    while (running) {
        // part x of the hard work
    }
    return null;
}

// ...
公共类MyTask扩展了AsyncTask{
private volatile boolean running=true;
//...
@凌驾
受保护的void onCancelled(){
运行=错误;
}
@凌驾
受保护的Void doInBackground(Void…参数){
//这项工作很辛苦吗
(跑步时){
//艰苦工作的第一部分
}
(跑步时){
//艰苦工作的第二部分
}
// ...
(跑步时){
//第十部分艰苦工作
   @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            LongOperationOdeme.cancel(true);
        }
        return super.onKeyDown(keyCode, event);
    }
if (backgroundTask != null) {
    backgroundTask.requestTermination();
    try {
        Thread.sleep((int)(0.5 * 1000));
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    if (backgroundTask.getStatus() != AsyncTask.Status.FINISHED) {
        backgroundTask.cancel(false);
    }
    backgroundTask = null;
}
public class MyTask extends AsyncTask<Void, Void, Void> {

private volatile boolean running = true;

//...

@Override
protected void onCancelled() {
    running = false;
}

@Override
protected Void doInBackground(Void... params) {

    // does the hard work

    while (running) {
        // part 1 of the hard work
    }

    while (running) {
        // part 2 of the hard work
    }

    // ...

    while (running) {
        // part x of the hard work
    }
    return null;
}

// ...
public class MyTask extends AsyncTask<Void, Void, Void> {

//...

@Override
protected Void doInBackground(Void... params) {

    // part 1 of the hard work
    // ...
    if (isCancelled()) {return null;}

    // part 2 of the hard work
    // ...
    if (isCancelled()) {return null;}

    // ...

    // part x of the hard work
    // ...
    if (isCancelled()) {return null;}
}

// ...