构造方法
在子线程中执行操作,并在主线程中处理操作结果。
public AsyncTask() {
mWorker = new WorkerRunnable<Params, Result>() {//WorkerRunnable实现了Callback接口
public Result call() throws Exception {
mTaskInvoked.set(true);
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
//noinspection unchecked
Result result = doInBackground(mParams);
Binder.flushPendingCommands();
return postResult(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);
}
}
};
}
生成一个Callback类型的mWorker,它内容有一个类型为Params[]的变量mParams;一个FutureTask类型的mFuture。executeOnExecutor
调用execute()时会执行到executeOnExecutor方法。如下:
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;
exec.execute(mFuture);
return this;
}
可以看出,首先进行了判断,然后调用onPreExecute(),再将传入的params赋值到mWorker的变量mParams。其中exec为execute传入的sDefaultExecutor。其具体实现如下:
private static class SerialExecutor implements Executor {
final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
Runnable mActive;
public synchronized void execute(final Runnable r) {
mTasks.offer(new Runnable() {
public void run() {
try {
r.run();
} finally {
scheduleNext();
}
}
});
if (mActive == null) {
scheduleNext();
}
}
protected synchronized void scheduleNext() {
if ((mActive = mTasks.poll()) != null) {
THREAD_POOL_EXECUTOR.execute(mActive);
}
}
}
在execute中,先会将一个Runnable对象添加到mTask中,这个对象的run()方法中会调用mFuture.run()。因此,只要执行到mTask中的对象,就会执行到当前的AsyncTask中的mFuture。
添加完后会对mActive进行判断,在执行第一个AsyncTask时,mActive==null是成立的,从而开始执行scheduleNext(),在该方法中会从mTask中取出一个对象执行其run()方法,这也就是开始执行mFuture.run()了。在每一个run()执行结束会接着调用scheduleNext(),这就形成了一个循环,保证了mTask中的所有对象都会被执行到。
在scheduleNext()中,会在线程池中执行mFuture,因此mFuture的run()方法执行在线程池中。
从这里也可以发现调用AsyncTask#execute()并不会立即执行该task,而是先将其添加到一个列表中,等它前面的所有task执行完毕之后才执行它。这也说明了:AsyncTask是串行执行的。如果想要立即执行该task,应该直接调用AsyncTask#executeOnExecutor()。
对于mTasks的类型,可参数集合中的ArrayDeque。
WorkRunnable#call
上面知道最终会在线程池中执行mFuture的run()方法,而该方法又会调用与mFuture关联的Callback#call(),即会调用mWork中的call()方法。其代码如下:
mWorker = new WorkerRunnable<Params, Result>() {
public Result call() throws Exception {
mTaskInvoked.set(true);
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
//noinspection unchecked
Result result = doInBackground(mParams);
Binder.flushPendingCommands();
return postResult(result);
}
};
这里终于调用了doInBackground(),而且是在线程池中调用的该方法,将其返回值传递到了postResult()中。
postResult()
其内部只是通过handler将结果发送一个Message。如下:
private Result postResult(Result result) {
@SuppressWarnings("unchecked")
Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
new AsyncTaskResult<Result>(this, result));
message.sendToTarget();
return result;
}
而在该getHandler()的handleMessage()中会调用AsyncTask#finish(),如下:
private void finish(Result result) {
if (isCancelled()) {
onCancelled(result);
} else {
onPostExecute(result);
}
mStatus = Status.FINISHED;
}
这里终于看到了onPostExecute()。而且它是在某个handler的handleMessage()方法中进行的调用。因此,onPostExecute()的执行线程将与getHandler返回的Handler的Looper直接相关:如果Looper是主线程的Looper,那么onPostExecute()将执行在UI线程中,否则将在子线程中执行的。
InternalHandler
上面的postResult()中调用了getHandler()方法,该方法返回的就是一个InternalHandler对象。其代码如下: private static class InternalHandler extends Handler {
public InternalHandler() {
super(Looper.getMainLooper());
}
@SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})
@Override
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;
}
}
}
非常开心,在构造方法中传入的是主线程的Looper,这就保证了onPostExecute()会执行在主线程。
cancel()
使用线程时,总会担心因为线程的原因导致内存泄漏(如Activity本身已经finish()了,但其内部仍有线程在执行,导致activity无法被回收)。AsyncTask提供了cancel方法,但这个方法并不是能瞬间停止线程的。如下:
public final boolean cancel(boolean mayInterruptIfRunning) {
mCancelled.set(true);
return mFuture.cancel(mayInterruptIfRunning);
}
第一句:将mCancelled设置为true,这是一个AtomicBoolean类型的变量,它是原子性的boolean,也赋值过程中不会被线程调度所打断,但它并不具备可见性(一个线程的修改对另外的线程都可见)。
第二句:调用了FutureTask#cancel()方法,其内部又调用了Thread#intercept(),这个只是发送一个停止当前线程的请求,并不能完全停止线程。因此,cancel并不会立即停止当前正在执行的线程。
为解决该问题,需要在doInBackground()中不断的满足是否被cancel掉了,如果是就不再执行doInbackground,这样线程才会被停止。
优先级
在AsyncTask中有一句:
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
这就是设置执行mWorker对象的线程的优先级。从这里可以看出,它的优先级是background(值为10,最低的优先级是19,值越大优先级越低)。对这个优先级的解释为:比正常的优先级要低,从而打断UI操作的机会变小。因此,AsyncTask打断UI操作的可能性比较小。
但在HandlerThread中,设置的是优先级是DEFAULE(值为0),而标准的前台线程的优先级是-2,所以从这里可以看出HandlerThread的优先级要远远高于AsyncTask,是介于后台线程与前台线程之间的。
总结
1,AsyncTask是串行执行的,如果想在立即执行需要调用executeOnExecutor()而不是execute()。
2,一个AsyncTask只能调用一次executeOnExecutor,无论是直接调用还是通过execute()调用。这个可以通过executeOnExecutor的源码判断出来。
3,由于在低版本(上面代码来源于API23)对于InternalHandler的定义方法不同,并且直接声明了一个静态的InternalHandler对象sHandler,所以为保证onPostExecute()正确地执行在UI线程中,并且在主线程中加载AsyncTask类。