AsyncTask是一种轻量级的异步任务类。从实现方式来说,AsyncTask封装了Thread和Handler,通过AsyncTask可以很方便的执行后台任务以及在主线程中访问UI,但是AsyncTask并不适合特别耗时的后台任务,对于特别耗时的任务来说还是建议使用线程池来实现。
AsyncTask主要提供了四种核心方法,
1)onPreExecute():在主线程执行,在异步任务执行之前,一般是做一些准备工作;
2) doInBackground(Params...Params):在线程池中执行,用于执行异步任务;这个方法中可以通过publishprogress方法来更新任务的进度,publishprogress方法会调用onProgressUpdate方法。另外这个方法需要返回结果给onPostExecute。
3) onProgressUpdate(Progress...Values):主线程运行,后台任务进度发生变化时被调用;
4) onPostExecute(Result result):主线程中执行,当异步任务执行结束后,会被调用。
除了以上方法AsyncTask还提供了onCancelled方法,在主线程执行,当异步任务被取消时会被调用。
注意:Android1.6以前AsyncTask是串行执行任务的,Android1.6以后AsyncTask开始使用线程池里并行任务,但是Android3.0以后,为了避免AsyncTask所带来的并发错误,AsyncTask又采用一个线程来串行执行任务。尽管如此,在Android3.0以及后面的版本中,我们仍然可以通过AsyncTask的executeOnExecutor方法来并行执行任务。
看过AsyncTask源码的同学都知道其实AsyncTask中有两个线程池(SerialExecytor和THREAD_POOL_EXECUTOR)和一个Handler(InternalHandler),其中SerialExecytor用于任务的排队,而线程池THREAD_POOL_EXECUTOR用于真正的执行任务,InternalHandler用于将执行环境从线程池切换到主线程。
private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
// We want at least 2 threads and at most 4 threads in the core pool,
// preferring to have 1 less than the CPU count to avoid saturating
// the CPU with background work
private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4));
private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
private static final int KEEP_ALIVE_SECONDS = 30;
private static final ThreadFactory sThreadFactory = new ThreadFactory() {
private final AtomicInteger mCount = new AtomicInteger(1);
public Thread newThread(Runnable r) {
return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());
}
};
private static final BlockingQueue<Runnable> sPoolWorkQueue =
new LinkedBlockingQueue<Runnable>(128);
/**
* An {@link Executor} that can be used to execute tasks in parallel.
*/
public static final Executor THREAD_POOL_EXECUTOR;
static {
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS,
sPoolWorkQueue, sThreadFactory);
threadPoolExecutor.allowCoreThreadTimeOut(true);
THREAD_POOL_EXECUTOR = threadPoolExecutor;
}
从AsyncTask源码可以看出,AsyncTask对THREAD_POOL_EXECUTOR这个线程池的配置。
------------------------------------------------------------------------
关于线程池,AsyncTask对应的线程池ThreadPoolExecutor都是进程范围内共享的,都是static的,所以是AsyncTask控制着进程范围内所有的子类实例。由于这个限制的存在,当使用默认线程池时,如果线程数超过线程池的最大容量,线程池就会爆掉(3.0默认串行执行,不会出现这个问题)。针对这种情况。可以尝试自定义线程池,配合AsyncTask使用。