在分析源碼以前,首先引用一段源碼中的註釋說明AsyncTask的定義:java
AsyncTask可以正確,方便的使用UI線程。AsyncTask能夠在不用使用Threads 和 handlers的狀況下,操做後臺線程而且將結果發送給UI線程。 AsyncTask是爲Thread和Handler而設計的幫助類,而且它應當使用在一些耗時較短的操做上,若是須要讓線程保持長時間的運行,強烈的推薦使用 java.util.concurrent包中的如Excutor、ThreadPoolExecutor、FutureTask。android
在分析源碼以前,先看一段簡單的使用例子,方便理解:ide
private class DownloadFilesTask extends AsyncTask(URL, Integer, Long) {
protected Long doInBackground(URL... urls) {
int count = urls.length;
long totalSize = 0;
for (int i = 0; i < count; i++) {
totalSize += Downloader.downloadFile(urls[i]);
//將進度返回給主線程,用於更新進度。
publishProgress((int) ((i / (float) count) * 100));
// Escape early if cancel() is called
if (isCancelled()) break;
}
return totalSize;
}
protected void onProgressUpdate(Integer... progress) {
setProgressPercent(progress[0]);
}
protected void onPostExecute(Long result) {
showDialog("Downloaded " + result + " bytes");
}
}
//調用
new DownloadFilesTask(url, 0, 1L).execute();
複製代碼
經過上面的例子咱們能夠看出AsyncTask的基本用法:就是用一個類繼承AsyncTask,而後分別實現三個方法: doInBackground()
、onProgressUpdate()
、onPostExecute()
。使用的時候,只須要調用execute()
方法便可。那麼下面咱們來看一下AsyncTask的源碼是怎麼實現的:oop
public abstract class AsyncTask<Params, Progress, Result> 複製代碼
AsyncTask是一個抽象類,而且包含了三個泛型參數,它們的含義咱們從名字應該能看得出來分別表示後臺任務的參數、進度、以及結果。 分別對應上面例子中的URL、Integer、Long。post
接下來咱們進入它的執行方法execute():this
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);
}
複製代碼
能夠看到,execute()調用了execureOnExecutor()這個方法 (關於execute()有一點須要說明的是,AsyncTask最初是使用串行的方式處理多任務,可是從Android 1.6開始,將其改成並行的,可是爲了不併行帶來的錯誤,自從Android 3.2 以後又改回了串行模式 ) ,那麼下面看看execureOnExecutor()的源代碼:url
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;
}
複製代碼
從上面代碼中能夠看出,首先會判斷當前AsyncTask的狀態是否爲等待狀態,若是不是則報錯,是等待狀態將會執行onPreExecute(),也就是咱們自定義的進行後臺任務前的方法。而後會調用exec的execute()方法,那麼這個exec是什麼呢? 從execute()方法的參數能夠看出,exec是一個叫作sDefaultExecutor的變量,那麼咱們去看看這個變量是什麼:spa
public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
複製代碼
原來是SerialExecutor這個類的一個對象,再繼續看看SerialExecutor這個類的定義:線程
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);
}
}
}
複製代碼
能夠看出,在SerialExecutor內部,實現了一個task任務的隊列(ArrayDeque),而且從這裏的處理,咱們也能看出來以前在execute()方法解釋的時候說任務是串行的原理了(註釋有說明),而實現任務的串行執行的正是THREAD_POOL_EXECUTOR,從名字就能夠看出來是一個線程池的定義,咱們先來看看對於這個線程池的定義:設計
//線程池核心線程數
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());
}
};
//大小爲128的阻塞隊列
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;
}
複製代碼
從上面的註釋咱們能夠看出,對於線程池的大小定義是和當前設備的CPU有關的,而核心線程數最大也不會超過4。那麼當若是線程數超過了最大線程數,其餘的只能阻塞排隊等待,那也就是說當有多個線程的時候不適合使用AsyncTask。
咱們再回到SerialExecutor類中,能夠看到在添加任務進隊列隊尾的時候,調用了r.run()這個方法,那麼咱們就須要知道這個r表明什麼,回看方法調用流程,咱們發如今executeOnExecutor()方法中,調用exec.execute()傳入了一個mFuture參數,那麼來看一下mFuture的定義:
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);
}
}
};
複製代碼
能夠看出,mFuture是一個FutureTask的對象,首先來看一下FutureTask的類定義:
public FutureTask(Runnable runnable, V result) {
this.callable = Executors.callable(runnable, result);
this.state = NEW; // ensure visibility of callable
}
...
public void run() {
if (state != NEW ||
!U.compareAndSwapObject(this, RUNNER, null, Thread.currentThread()))
return;
try {
Callable<V> c = callable;
if (c != null && state == NEW) {
V result;
boolean ran;
try {
//調用Callable的call()
result = c.call();
ran = true;
} catch (Throwable ex) {
result = null;
ran = false;
setException(ex);
}
if (ran)
//將結果保存起來
set(result);
}
} finally {
// runner must be non-null until state is settled to
// prevent concurrent calls to run()
runner = null;
// state must be re-read after nulling runner to prevent
// leaked interrupts
int s = state;
if (s >= INTERRUPTING)
handlePossibleCancellationInterrupt(s);
}
}
複製代碼
FutureTask的參數爲一個runnable與一個Result的對象,FutureTask是一個能夠執行runnable,而且返回執行結果result的類。以前提到,在SerialExecutor中調用了FutureTask的run方法,從上面的run方法定義中能夠看出,其實是調用了傳入的runnable轉換後的Callable的call(),而且將結果保存起來,而後返回:
protected void set(V v) {
if (U.compareAndSwapInt(this, STATE, NEW, COMPLETING)) {
outcome = v;
U.putOrderedInt(this, STATE, NORMAL); // final state
finishCompletion();
}
}
...
private void finishCompletion() {
...
done();
callable = null; // to reduce footprint
}
複製代碼
最後經過調用done()方法,表示已經運行完畢。
到這裏咱們發現,實際上最終運行的是FutureTask中的這個Runnable,那麼回到mFutureTask的定義,看到傳入的是一個mWorker,那麼看看mWorker的定義
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;
}
};
...
private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> {
Params[] mParams;
}
複製代碼
能夠看到,mWorker就是一個Callable對象,而且在其call()方法內,調用了doInBackground()也就是咱們自定義的後臺操做,在返回結果以後,再調用postResult()返回給主線程:
private Result postResult(Result result) {
@SuppressWarnings("unchecked")
Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
new AsyncTaskResult<Result>(this, result));
message.sendToTarget();
return result;
}
複製代碼
能夠看到,postResult內部也是使用handler去返回給主線程的,而後再來看看Handler的定義:
private static class InternalHandler extends Handler {
public InternalHandler(Looper looper) {
super(looper);
}
@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
// 調用finish方法,並將result返回
result.mTask.finish(result.mData[0]);
break;
case MESSAGE_POST_PROGRESS:
result.mTask.onProgressUpdate(result.mData);
break;
}
}
}
複製代碼
能夠看到,在Handler中調用了finish()這個方法:
private void finish(Result result) {
if (isCancelled()) {
onCancelled(result);
} else {
onPostExecute(result);
}
mStatus = Status.FINISHED;
}
複製代碼
在finish中,將結果返回給用戶,調用咱們自定義的onPostExecute,而且將當前的狀態置爲FINISHED,完成了整個流程。