取消执行AsyncTask的理想方法

Sam*_*muh 107 android android-asynctask

我在后台线程中运行远程音频文件获取和音频文件播放操作AsyncTask.甲Cancellable进度条示出了用于提取操作运行的时间.

我想AsyncTask在用户取消(决定)操作时取消/中止运行.处理这种情况的理想方式是什么?

yan*_*nko 78

才发现,原来AlertDialogsboolean cancel(...);我已经用实际处处什么也不做.大.
所以...

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

    private volatile boolean running = true;
    private final ProgressDialog progressDialog;

    public MyTask(Context ctx) {
        progressDialog = gimmeOne(ctx);

        progressDialog.setCancelable(true);
        progressDialog.setOnCancelListener(new OnCancelListener() {
            @Override
            public void onCancel(DialogInterface dialog) {
                // actually could set running = false; right here, but I'll
                // stick to contract.
                cancel(true);
            }
        });

    }

    @Override
    protected void onPreExecute() {
        progressDialog.show();
    }

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

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

        while (running) {
            // does the hard work
        }
        return null;
    }

    // ...

}
Run Code Online (Sandbox Code Playgroud)

  • 而不是为运行做一个布尔标志,你不能​​删除它,并在(!isCanceled())??? (55认同)
  • 来自关于onCancelled()的文档:"在调用**cancel(boolean)之后运行UI线程**并且doInBackground(Object [])已经完成." 这个'之后'意味着在onCancelled中设置一个标志并检入doInBackground是没有意义的. (35认同)
  • 是的,这个答案**不起作用**.在doInBackground中,将'while(running)`替换为`while(!isCancelled())`,正如其他人在评论中所说的那样. (4认同)
  • @confucius说得对,但是这样后台线程不会被中断,假设在上传图片的情况下,上传过程在后台继续,我们没有得到onPostExecute调用. (2认同)

wry*_*iel 76

如果你正在进行计算:

  • 你必须isCancelled()定期检查.

如果您正在执行HTTP请求:

  • 保存您HttpGetHttpPost某处的实例(例如,公共字段).
  • 打电话后cancel,打电话request.abort().这将导致IOException你的内心被抛出doInBackground.

在我的例子中,我有一个连接器类,我在各种AsyncTasks中使用它.为了简单起见,我abortAllRequests在该类中添加了一个新方法,并在调用后直接调用此方法cancel.


小智 20

问题是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;
        }
     }
Run Code Online (Sandbox Code Playgroud)

  • 正如在接受的答案的评论中所提到的,没有必要创建自己的`running`标志.AsyncTask有一个内部标志,在任务被取消时设置.用`while(!isCancelled())`替换`while(running)`.http://developer.android.com/reference/android/os/AsyncTask.html#isCancelled()所以在这个简单的例子中,你不需要`onCancelled()`覆盖. (4认同)
  • 这将起作用,但是在逻辑上,当您等待服务器响应时,您刚刚执行了db操作,则应该反映对活动的正确更改。我为此写了博客,请参阅我的答案。 (2认同)

Com*_*are 11

简单:不要使用AsyncTask.AsyncTask设计用于快速结束(数十秒)的短操作,因此不需要取消."音频文件播放"不符合条件.您甚至不需要后台线程来播放普通音频文件.

  • 没有进攻迈克,但这不是一个可接受的答案.AsyncTask有一个取消方法,它应该工作.据我所知,它没有 - 但即使我做错了,那么应该有一种正确的方法来取消任务.否则该方法将不存在.即使是短任务也可能需要取消 - 我有一个Activity,它会在加载后立即开始AsyncTask,如果用户在打开任务后立即回击,他们会在任务完成后看到强制关闭,但没有上下文它存在于onPostExecute中使用. (33认同)
  • @Klondike:我不知道"Mike"是谁."但这不是一个可以接受的答案" - 欢迎你的意见."AsyncTask有一个取消方法,它应该可以工作." - 取消Java中的线程已经存在了大约15年的问题.它与Android没什么关系.关于你的"Force Close"场景,可以通过一个布尔变量来解决,你可以在`onPostExecute()`中测试它是否应该继续工作. (10认同)
  • 您应该在AsyncTask上的doInBackground中定期检查isCancelled方法.它就在文档中:http://developer.android.com/reference/android/os/AsyncTask.html#isCancelled() (10认同)