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;}
}
// ...