前言
说起AsyncTask,我们既熟悉又陌生,它内部封装Thread和Handler。说起频繁在早些年开发时候用他也是非常的频繁,说起陌生google开发人员这几年也在维护着,具体变化如下:
- Api 4(1.6)之前串行执行任务,在Api 4(包含)到Api 11(3.0)修改成并发执行任务,然后Api 11到现在的Api 29(10.0)都是串行执行任务。
- 当我们在实例化AsyncTask对象时候,在Api 21 (5.0)(之前包含)不能在子线程实例化,在Api 22 (5.1)(包含以后)可以实现在子线程实例化,参考AsyncTask主线程实例化。
源码分析
我们开始分析AsyncTask源码,不管是串行或者并行我们都可以通过调用代码实现,解下来我们通过源码来逐一分析,将会把代码分段式贴出来讲解。
//1
private static final int CORE_POOL_SIZE = 1;
//2
private static final int MAXIMUM_POOL_SIZE = 20;
private static final int BACKUP_POOL_SIZE = 5;
//3
private static final int KEEP_ALIVE_SECONDS = 3;
private static final ThreadFactory sThreadFactory = new ThreadFactory() {
//4
private final AtomicInteger mCount = new AtomicInteger(1);
public Thread newThread(Runnable r) {
return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());
}
};
- CORE_POOL_SIZE 是线程池核心容量,核心线程在线程池会一直存活,即时他处于空闲状态。如果设置ThreadPoolExecutor的allowCoreThreadTimeOut属性为true,那么闲置的核心线程在等待新任务时候也有超时时间,这个时间由keepAliveTime指定,超过这个时间还在闲置即可终止。
- MAXIMUM_POOL_SIZE 是线程池最大容量,当活跃线程到达这个值时新的任务阻塞。
- KEEP_ALIVE_SECONDS 非核心线程的超时终止时间,如果设置ThreadPoolExecutor的allowCoreThreadTimeOut属性为true,那么空闲核心线程也是这个时间终止。
- 原子整数,保证超高并发下工作。
public static final Executor THREAD_POOL_EXECUTOR;
//1
static {
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>(), sThreadFactory);
threadPoolExecutor.setRejectedExecutionHandler(sRunOnSerialPolicy);
THREAD_POOL_EXECUTOR = threadPoolExecutor;
}
//2
public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
//3
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
- THREAD_POOL_EXECUTOR 静态并发线程池,可以用来执行并发任务,尽管Api 11(3.0)开始,AsyncTask串行执行任务,从这代码也能说明,我们可以使用并行的AsyncTask。
- 创建 SERIAL_EXECUTOR 静态的串行控制器。
- sDefaultExecutor 为默认任务执行器,赋值SERIAL_EXECUTOR给它,所以现在的AsyncTask变成了串行执行器。
接下来我们看看串行任务器是如何实现的,代码如下:
private static class SerialExecutor implements Executor {
//1
final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
Runnable mActive;
public synchronized void execute(final Runnable r) {
//2
mTasks.offer(new Runnable() {
public void run() {
try {
//执行任务
r.run();
} finally {
//3
scheduleNext();
}
}
});
//4
if (mActive == null) {
scheduleNext();
}
}
protected synchronized void scheduleNext() {
//5
if ((mActive = mTasks.poll()) != null) {
THREAD_POOL_EXECUTOR.execute(mActive);
}
}
}
SerialExecutor 类继承Executor,实现串行任务执行器。
- mTasks 可变数组,没有容量限制,效率高于Stack和队列。
- 将新任务添加到双向队列的末尾插入,并且把r再次包装在Runnable里面,目的是便于执行scheduleNext方法。
- 当任务执行完了后,调用scheduleNext方法 ,再执行下一个任务,典型的串行执行方式,任务总是一个执行完了后在执行新的任务。
- 当没有任务执行,开始执行新任务。
- 从任务队列中获取任务,然后放到并发线程池执行。
/**
* Creates a new asynchronous task. This constructor must be invoked on the UI thread.
*/
//1
public AsyncTask() {
this((Looper) null);
}
/**
* Creates a new asynchronous task. This constructor must be invoked on the UI thread.
*
* @hide
*/
public AsyncTask(@Nullable Looper callbackLooper) {
//2
mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper()
? getMainHandler()
: new Handler(callbackLooper);
mWorker = new WorkerRunnable<Params, Result>() {
public Result call() throws Exception {
mTaskInvoked.set(true);
Result result = null;
try {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
//noinspection unchecked
result = doInBackground(mParams);
Binder.flushPendingCommands();
} catch (Throwable tr) {
mCancelled.set(true);
throw tr;
} finally {
postResult(result);
}
return result;
}
};
mFuture = new FutureTask<Result>(mWorker) {
@Override
protected void done() {
try {
postResultIfNotInvoked(get());
} catch (InterruptedException e) {
android.util.Log.w(LOG_TAG, e);
} catch (ExecutionException e) {
throw new RuntimeException("An error occurred while executing doInBackground()",
e.getCause());
} catch (CancellationException e) {
postResultIfNotInvoked(null);
}
}
};
}
//3
private static Handler getMainHandler() {
synchronized (AsyncTask.class) {
if (sHandler == null) {
//4
sHandler = new InternalHandler(Looper.getMainLooper());
}
return sHandler;
}
}
- 从注释来看“This constructor must be invoked on the UI thread”,它说必须在主线程实例化,其实这是用的Api 21的注释,不知道谷歌开发人员为何不修改。AsyncTask的无参构造函数,在Api 21 以后都可以在子线程创建实例。在此类中只有一个构造函数提供给开发人员调用,其他构造函数用了@hide注解。
- 构造函数只有一个,推测出参数callbackLooper肯定为空,接着调用了getMainHandler方法。从这个构造函数可以推测一下,以后可能会传递自定义looper参数进行实例化。
- 获取主线程的Handler对象,用于发送消息到主线程。
- 创建用于主线程的handler。
通过第1点和第4点看出mHandler和sHandler引用指向同一个对象。了解构造函数后,我们继续看如何执行任务。
/** @hide */
@UnsupportedAppUsage
//1
public static void setDefaultExecutor(Executor exec) {
sDefaultExecutor = exec;
}
@MainThread
//2
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);
}
//3
@MainThread
public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
Params... params) {
if (mStatus != Status.PENDING) {
switch (mStatus) {
case RUNNING:
throw new IllegalStateException("Cannot execute task:"
+ " the task is already running.");
case FINISHED:
throw new IllegalStateException("Cannot execute task:"
+ " the task has already been executed "
+ "(a task can be executed only once)");
}
}
mStatus = Status.RUNNING;
//准备执行时调用,回调在调用者线程
onPreExecute();
mWorker.mParams = params;
//然后执行doInBackground
exec.execute(mFuture);
return this;
}
@MainThread
//4
public static void execute(Runnable runnable) {
sDefaultExecutor.execute(runnable);
}
@MainThread 提醒我们要在主线程调用,上面讲过这都是遗留下的注释,我们可以不管。
- 为AsyncTask设置默认执行器,且隐藏Api 。
- 开始执行任务。
- 我们可以自定义AsyncTask的执行方式串行或者并发,甚至可以自定义Executor来实现多线程并发。
- 静态方法执行一个Runnable。
接下来我们继续看,AsyncTask的方法回调。
private static class InternalHandler extends Handler {
public InternalHandler(Looper looper) {
super(looper);
}
@SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})
@Override
//1
public void handleMessage(Message msg) {
AsyncTaskResult<?> result = (AsyncTaskResult<?>) msg.obj;
switch (msg.what) {
case MESSAGE_POST_RESULT:
// There is only one result
result.mTask.finish(result.mData[0]);
break;
case MESSAGE_POST_PROGRESS:
result.mTask.onProgressUpdate(result.mData);
break;
}
}
}
//2
private Result postResult(Result result) {
@SuppressWarnings("unchecked")
Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
new AsyncTaskResult<Result>(this, result));
message.sendToTarget();
return result;
}
//3
protected final void publishProgress(Progress... values) {
if (!isCancelled()) {
getHandler().obtainMessage(MESSAGE_POST_PROGRESS,
new AsyncTaskResult<Progress>(this, values)).sendToTarget();
}
}
//4
private void finish(Result result) {
if (isCancelled()) {
onCancelled(result);
} else {
onPostExecute(result);
}
mStatus = Status.FINISHED;
}
- 处理来之结果和更新进度的消息。
- 当doInBackground执行完毕后或者调用AsyncTask的cancel方法调用postResult方法。
- 当在doInBackground方法中执行任务时,可以告知调用者现在任务执行进度,通过调用publishProgress方法,调用者在 onProgressUpdate方法中即可得到进度,onProgressUpdate方法在主线程中运行。
- 在finish方法判断任务是否是被取消,取消则调用onCancelled方法,正常则调用onPostExecute方法,上述两个方法在主线程执行且回调这两个方法是互斥的。
这些都是所有关于AsyncTask源码分析。