概述
AsyncTask是一个轻量级选手,适合处理轻量级的后台任务。处理过程中还可以把处理的进度反馈到主线程中,方便我们更新UI,不需要我们去操作 handler,在早期 Android 版本中是十分方便的工具。但是如果用的不好会引入不少奇怪的问题!
1. Cancel 取消任务不生效
在基础篇 AsyncTask - 基础篇 介绍 Cancel 的时候:
if (myAsyncTask!=null)
myAsyncTask.cancel(true);
通过 cancel 来取消任务,最终会调用到,FutureTask 里面的 cancel 方法,可这样真的会被终止吗?可不一定。FutureTask 可以理解为实际上就是一个线程,cancel() 方法改变了 futureTask 的状态位,
- 如果传入的是false并且业务逻辑已经开始执行,当前任务是不会被终止的,而是会继续执行,直到异常或者执行完毕。
- 如果传入的是true,会调用当前线程的interrupt()方法,把中断标志位设为true。
而 Thread.interrupt() 方法,是提示一个线程应该终止,但不强制该线程终止。所以,AsyncTask.cancel 并不能保证取消任务。
那我们该怎么解决呢?其实,AsyncTask.cancel 在调用后,会改变 AsyncTask.isCancelled() 的返回值,我们在 doInBackground 中就需要时刻去判断这个返回值,放判断到已经取消了,我们要及时地退出任务:
@Override
protected Boolean doInBackground(String... strings) {
Log.i(TAG,"doInBackground...");
int i=0;
while(i<100){
if (isCancelled())
break;
i++;
//任务执行过程进度/参数的回调,对应于泛型:Progress
publishProgress(i);
try {
Thread.sleep(200);
} catch (InterruptedException ignored) {
}
}
//返回值代表最后的结果,对应于泛型:Result
return true;
}
上面程序模拟耗时操作,在每次for循环的开始,都去判断是否已经取消了任务,当取消了任务后就没必要继续执行了,直接break结束。
2. 内存泄漏
AsyncTask 提供了几个运行在主线程的方法给我们重写,我们可以在里面进行UI的更新,但是呢,因为我们要更新UI对