一、 什么是AsyncTask
它本质上就是封装了线程池和handler的异步框架
二、 AsyncTask的使用方法
- 三个参数
- 参数1 Integer 执行AsyncTask时,传入的参数,可在后台任务中使用
- 参数2 Integer 在后台执行任务时,在界面上显示当前的进度
- 参数3 String 异步任务执行完成后,如果需要对结果进行返回,使用String作为返回的值
- 5个方法
- onPreExecute
- doInBackground
- publishProgress
- onProgressUpdate
- onPostExecute
public class UpdateInfoAsyncTask extends AsyncTask<Integer, Integer, String> {
/**
* 参数1 Integer 执行AsyncTask时,传入的参数,可在后台任务中使用
* 参数2 Integer 在后台执行任务时,在界面上显示当前的进度
* 参数3 String 异步任务执行完成后,如果需要对结果进行返回,使用String作为返回的值
*/
// 在耗时操作开始前,进行初始化操作,在UI线程中调用,例如显示进度条等
@Override
protected void onPreExecute() {
super.onPreExecute();
}
// 执行耗时操作,在onPreExecute调用完成后调用,返回执行的结果
@Override
protected String doInBackground(Integer... integers) {
int i;
for (i = 10; i <= 100; i+=10) {
// 发布一个进度单位, 可以不断渐变显示后台进行的计算
publishProgress(i);
}
return i + integers[0].intValue() + "";
}
// 在主线程中动态显示线程任务执行的进度,在publishProgress后调用
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
}
// 后台计算完成后调用,后台的结果通过String s传递给该方法
@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
}
}
三、 AsyncTask内部原理
- AsyncTask的本质是一个静态的线程池,AsyncTask派生出的子类可以实现不同的异步任务,这些任务都是提交到静态的线程池中执行
- 线程池的工作线程执行doInBackgroud(mParams)方法执行异步任务
- 当任务状态改变之后,工作线程会向UI线程发送消息,AsyncTask内部的InternalHandler响应这些消息,并调用相关的回调函数。
四、 AsyncTask的注意事项
- 内存泄漏
跟Handler的内存泄漏相似,非静态内部类持有外部类的引用,由于activity被销毁,但是AsyncTask还在执行任务,所以此时AsyncTask将持有activity的引用,导致activity想被摧毁时无法被内存回收,引起了内存泄漏。
解决内存泄漏:弱引用,静态内部类,在activity中的onDestroy中调用asyncTask的cancle方法 - 生命周期
AsyncTask不会随着activity的销毁而销毁,如果没有调用asyncTask的cancle方法,是不会被销毁的。 - 结果丢失
在屏幕旋转或activity由于内存不够被杀掉导致activity重新创建,而之前运行的AsyncTask会持有之前的activity引用, 但是之前的引用已经无效了,所以此时调用AsyncTask的onPostExecute方法去更新界面不会生效。有可能会导致崩溃。 - 并行or串行
在android 1.6 前AsyncTask都是串行,把所有的任务一串一串的放在线程池中有序的进行执行,而在1.6-2.3版本后改成了并行,2.3后又改成了串行。但是还可以调用excute方法可以并行,建议一般情况下只使用串行,这个可以保持整个线程池的稳定。如果并发的话线程池是不稳定的,虽然效率很高。 AsyncTask做不了高并发,太耗时的操作。