android - Android/AsyncTask:你还需要检查“isCancelled”(API 24)吗?
问题描述
我的应用程序使用 anAsyncTask
来下载文件,同时显示ProgressDialog
带有“取消”按钮的(我知道它已被弃用)。
根据这一点,您应该定期检查isCancelled()
,因为不会自行中断。doInBackground
mytask.cancel(true)
doInBackground
我一开始没有检查就简单地取消了任务,并注意到它仍然停止doInBackground
:根据我在按下“取消”按钮之前让它下载多长时间,我在生成的文件中看到了不同的大小——从几 kb 到一个几个 mb - 最终大小约为 9mb。
这怎么可能?你真的不用再打电话isCancelled()
了吗?
我的异步任务:
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();
//....
}
解决方案
根据这一点,您应该定期检查 doInBackground 中的 isCancelled() ,因为 mytask.cancel(true) 不会自行中断 doInBackground 。
实际上这不是真的。
根据文件:
调用此方法后,应定期从 doInBackground(Object[]) 中检查 isCancelled() 返回的值,以尽早完成任务。
这意味着您还可以检查是否已启动更早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
在您的情况下可以停止 io 阻塞操作。
推荐阅读
- python - 查找数据框的所有可能组合
- android - Xamarin Android 中基于 Unity 的依赖解析的 MissingMethodException
- c# - 拒绝访问端口“com8”。这段代码的错误在哪里?
- angular - 如何将字体真棒库提取到一个单独的库中?
- sql - 在 Oracle PLSQL 中,如果列中已包含数值,则无法使用字母数字更新 VARCHAR2 列
- oracle - PLS-00103:预期错误时遇到符号“文件结尾”
- sql-server - 将 Varbinary 转换为 XML 时的 TSQL“非法 XML 字符”
- excel - 实现更改事件以检查文本框值的更改并启用“应用”按钮
- r - 在 redHat CentOs 7 上安装 R。我无法克服的几个错误和依赖项
- angular - ngFor 查找第一个和最后一个以及总索引