我的应用使用AsyncTask
下载文件,同时显示ProgressDialog
(我意识到它已被弃用),其中包含"取消"按钮。
根据this,您应定期检查isCancelled()
中的doInBackground
,因为mytask.cancel(true)
不会自行中断doInBackground
。
我只是在没有检查的情况下取消了任务,发现它仍然停止doInBackground
:取决于我按下"取消"按钮,我在生成的文件中看到了不同的尺寸 - 从几kb到几mb - 最终尺寸大约为9mb。
这怎么可能?你真的不必再打电话给isCancelled()
吗?
我的AsyncTask:
private class DownloadTask extends AsyncTask<String, String, String> {
protected void onPreExecute() {
progressdialog.setMessage("Preparing Download...");
progressdialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progressdialog.setProgressNumberFormat(null);
progressdialog.setProgressPercentFormat(null);
progressdialog.setIndeterminate(true);
progressdialog.setButton(DialogInterface.BUTTON_NEGATIVE, "Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
progressdialog.dismiss();
mytask.cancel(true);
}
});
progressdialog.show();
}
protected String doInBackground(String... bla) {
String error = download();
return error;
}
protected void onProgressUpdate(String... s) {
//....
}
protected void onPostExecute(String s) {
progressdialog.dismiss();
//....
}
答案 0 :(得分:1)
根据这个你应该在doInBackground中检查isCancelled() 定期因为mytask.cancel(true)不会中断 doInBackground本身。
实际上并非如此。
调用此方法后,应检查返回的值 isCancelled()定期从doInBackground(Object [])来完成 尽早完成任务。
这意味着您可以另外检查isCancelled()
是否先停止AsyncTask
,如果它已启动。
mytask.cancel(true)无论如何都会停止执行。
让我们看看幕后发生了什么
致电mytask.cancel(true)
时:
public final boolean cancel(boolean mayInterruptIfRunning) {
mCancelled.set(true);
return mFuture.cancel(mayInterruptIfRunning);
}
其中mFuture
是FutureTask
,其中包含可运行的
然后调用mFuture.cancel
:
public boolean cancel(boolean mayInterruptIfRunning) {
if (state != NEW)
return false;
if (mayInterruptIfRunning) {
if (!UNSAFE.compareAndSwapInt(this, stateOffset, NEW, INTERRUPTING))
return false;
Thread t = runner;
if (t != null)
t.interrupt();
UNSAFE.putOrderedInt(this, stateOffset, INTERRUPTED); // final state
}
else if (!UNSAFE.compareAndSwapInt(this, stateOffset, NEW, CANCELLED))
return false;
finishCompletion();
return true;
}
runner
只是
private volatile Thread runner;
由于它只是线程,让我们看看interrupt
在您的情况下做了什么:
如果此线程在可中断的I / O操作中被阻止 然后通道将关闭,线程的中断状态 将被设置,线程将收到ClosedByInterruptException。
因此,如果您的download()
方法使用InterruptibleChannel
interrupt
即可。
换句话说,您似乎从未调用isCancelled()
来中断AsyncTask
=),因为Thread.interrupt
可以阻止您的阻止操作。