
前言
-
AsyncTask在Android開發(fā)中是十分常見的 - 今天,我將全面講解
AsyncTask的源碼,希望你們會喜歡
Carson帶你學(xué)多線程系列
基礎(chǔ)匯總
Android多線程:基礎(chǔ)知識匯總
基礎(chǔ)使用
Android多線程:繼承Thread類使用(含實例教程)
Android多線程:實現(xiàn)Runnable接口使用(含實例教程)
復(fù)合使用
Android 多線程:AsyncTask使用教程(含實例講解)
Android 多線程:AsyncTask原理及源碼分析
Android多線程:HandlerThread使用教程(含實例講解)
Android多線程:HandlerThread原理及源碼分析
Android多線程:IntentService使用教程(含實例講解)
Android多線程:IntentService的原理及源碼分析
Android多線程:線程池ThreadPool全方位教學(xué)
相關(guān)使用
Android異步通信:這是一份全面&詳細(xì)的Handler機制學(xué)習(xí)攻略
Android多線程:手把手教你全面學(xué)習(xí)神秘的Synchronized關(guān)鍵字
Android多線程:帶你了解神秘的線程變量 ThreadLocal
目錄

1. 簡介

更詳細(xì)了解,請看文章:Android 多線程:AsyncTask最詳細(xì)使用教程
本文主要講解其工作原理 & 源碼分析
2. 工作原理
2.1 儲備知識:線程
- 簡介

- 與進程的區(qū)別

2.2 具體原理介紹
-
AsyncTask的實現(xiàn)原理 = 線程池 +Handler
其中:線程池用于線程調(diào)度、復(fù)用 & 執(zhí)行任務(wù);
Handler用于異步通信
- 其內(nèi)部封裝了2個線程池 + 1個
Handler,具體介紹如下:

3. 類 & 方法介紹
在進行源碼分析前,先介紹AsyncTask中的類 & 核心方法
3.1 類定義
AsyncTask類屬于抽象類,即使用時需 實現(xiàn)子類
public abstract class AsyncTask<Params, Progress, Result> {
...
}
// 類中參數(shù)為3種泛型類型
// 整體作用:控制AsyncTask子類執(zhí)行線程任務(wù)時各個階段的返回類型
// 具體說明:
// a. Params:開始異步任務(wù)執(zhí)行時傳入的參數(shù)類型,對應(yīng)excute()中傳遞的參數(shù)
// b. Progress:異步任務(wù)執(zhí)行過程中,返回下載進度值的類型
// c. Result:異步任務(wù)執(zhí)行完成后,返回的結(jié)果類型,與doInBackground()的返回值類型保持一致
// 注:
// a. 使用時并不是所有類型都被使用
// b. 若無被使用,可用java.lang.Void類型代替
// c. 若有不同業(yè)務(wù),需額外再寫1個AsyncTask的子類
}
3.2 核心方法
-
AsyncTask核心 & 常用的方法如下:

- 方法執(zhí)行順序如下

4. 源碼分析
- 本次源碼分析將根據(jù)
AsyncTask的使用步驟講解
若不熟悉,請務(wù)必看文章:Android 多線程:AsyncTask最詳細(xì)使用教程
-
AsyncTask的使用步驟有3個:
- 創(chuàng)建
AsyncTask子類 & 根據(jù)需求實現(xiàn)核心方法 - 創(chuàng)建
AsyncTask子類的實例對象(即 任務(wù)實例) - 手動調(diào)用
execute(()從而執(zhí)行異步線程任務(wù)
- 具體介紹如下
/**
* 步驟1:創(chuàng)建AsyncTask子類
* 注:
* a. 繼承AsyncTask類
* b. 為3個泛型參數(shù)指定類型;若不使用,可用java.lang.Void類型代替
* c. 根據(jù)需求,在AsyncTask子類內(nèi)實現(xiàn)核心方法
*/
private class MyTask extends AsyncTask<Params, Progress, Result> {
....
// 方法1:onPreExecute()
// 作用:執(zhí)行 線程任務(wù)前的操作
// 注:根據(jù)需求復(fù)寫
@Override
protected void onPreExecute() {
...
}
// 方法2:doInBackground()
// 作用:接收輸入?yún)?shù)、執(zhí)行任務(wù)中的耗時操作、返回 線程任務(wù)執(zhí)行的結(jié)果
// 注:必須復(fù)寫,從而自定義線程任務(wù)
@Override
protected String doInBackground(String... params) {
...// 自定義的線程任務(wù)
// 可調(diào)用publishProgress()顯示進度, 之后將執(zhí)行onProgressUpdate()
publishProgress(count);
}
// 方法3:onProgressUpdate()
// 作用:在主線程 顯示線程任務(wù)執(zhí)行的進度
// 注:根據(jù)需求復(fù)寫
@Override
protected void onProgressUpdate(Integer... progresses) {
...
}
// 方法4:onPostExecute()
// 作用:接收線程任務(wù)執(zhí)行結(jié)果、將執(zhí)行結(jié)果顯示到UI組件
// 注:必須復(fù)寫,從而自定義UI操作
@Override
protected void onPostExecute(String result) {
...// UI操作
}
// 方法5:onCancelled()
// 作用:將異步任務(wù)設(shè)置為:取消狀態(tài)
@Override
protected void onCancelled() {
...
}
}
/**
* 步驟2:創(chuàng)建AsyncTask子類的實例對象(即 任務(wù)實例)
* 注:AsyncTask子類的實例必須在UI線程中創(chuàng)建
*/
MyTask mTask = new MyTask();
/**
* 步驟3:手動調(diào)用execute(Params... params) 從而執(zhí)行異步線程任務(wù)
* 注:
* a. 必須在UI線程中調(diào)用
* b. 同一個AsyncTask實例對象只能執(zhí)行1次,若執(zhí)行第2次將會拋出異常
* c. 執(zhí)行任務(wù)中,系統(tǒng)會自動調(diào)用AsyncTask的一系列方法:onPreExecute() 、doInBackground()、onProgressUpdate() 、onPostExecute()
* d. 不能手動調(diào)用上述方法
*/
mTask.execute();
- 下面,我將根據(jù)上述使用步驟進行源碼分析
步驟1:創(chuàng)建AsyncTask子類
在該步驟中,只需知道 “該類中復(fù)寫的方法將在后續(xù)源碼中調(diào)用” 即可
步驟2:創(chuàng)建AsyncTask子類的實例對象(即 任務(wù)實例)
/**
* 具體使用
*/
MyTask mTask = new MyTask();
/**
* 源碼分析:AsyncTask的構(gòu)造函數(shù)
*/
public AsyncTask() {
// 1. 初始化WorkerRunnable變量 = 一個可存儲參數(shù)的Callable對象 ->>分析1
mWorker = new WorkerRunnable<Params, Result>() {
// 在任務(wù)執(zhí)行線程池中回調(diào):THREAD_POOL_EXECUTOR.execute()
// 下面會詳細(xì)講解
public Result call() throws Exception {
// 添加線程的調(diào)用標(biāo)識
mTaskInvoked.set(true);
Result result = null;
try {
// 設(shè)置線程的優(yōu)先級
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
// 執(zhí)行異步操作 = 耗時操作
// 即 我們使用過程中復(fù)寫的耗時任務(wù)
result = doInBackground(mParams);
Binder.flushPendingCommands();
} catch (Throwable tr) {
mCancelled.set(true);// 若運行異常,設(shè)置取消的標(biāo)志
throw tr;
} finally {
// 把異步操作執(zhí)行的結(jié)果發(fā)送到主線程
// 從而更新UI,下面會詳細(xì)講解
postResult(result);
}
return result;
}
};
// 2. 初始化FutureTask變量 = 1個FutureTask ->>分析2
mFuture = new FutureTask<Result>(mWorker) {
// done()簡介:FutureTask內(nèi)的Callable執(zhí)行完后的調(diào)用方法
// 作用:復(fù)查任務(wù)的調(diào)用、將未被調(diào)用的任務(wù)的結(jié)果通過InternalHandler傳遞到UI線程
@Override
protected void done() {
try {
// 在執(zhí)行完任務(wù)后檢查,將沒被調(diào)用的Result也一并發(fā)出 ->>分析3
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) {
//若 發(fā)生異常,則將發(fā)出null
postResultIfNotInvoked(null);
}
}
};
}
/**
* 分析1:WorkerRunnable類的構(gòu)造函數(shù)
*/
private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> {
// 此處的Callable也是任務(wù);
// 與Runnable的區(qū)別:Callable<T>存在返回值 = 其泛型
Params[] mParams;
}
/**
* 分析2:FutureTask類的構(gòu)造函數(shù)
* 定義:1個包裝任務(wù)的包裝類
* 注:內(nèi)部包含Callable<T> 、增加了一些狀態(tài)標(biāo)識 & 操作Callable<T>的接口
*/
public FutureTask(Callable<V> callable) {
if (callable == null)
throw new NullPointerException();
this.callable = callable;
this.state = NEW;
}
// 回到調(diào)用原處
/**
* 分析3:postResultIfNotInvoked()
*/
private void postResultIfNotInvoked()(Result result) {
// 取得任務(wù)標(biāo)記
final boolean wasTaskInvoked = mTaskInvoked.get();
// 若任務(wù)無被執(zhí)行,將未被調(diào)用的任務(wù)的結(jié)果通過InternalHandler傳遞到UI線程
if (!wasTaskInvoked) {
postResult(result);
}
}
總結(jié):
- 創(chuàng)建了1個
WorkerRunnable類 的實例對象 & 復(fù)寫了call()方法 - 創(chuàng)建了1個
FutureTask類 的實例對象 & 復(fù)寫了done()
步驟3:手動調(diào)用execute(Params... params)
/**
* 具體使用
*/
mTask.execute();
/**
* 源碼分析:AsyncTask的execute()
*/
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);
// ->>分析1
}
/**
* 分析1:executeOnExecutor(sDefaultExecutor, params)
* 參數(shù)說明:sDefaultExecutor = 任務(wù)隊列 線程池類(SerialExecutor)的對象
*/
public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,Params... params) {
// 1. 判斷 AsyncTask 當(dāng)前的執(zhí)行狀態(tài)
// PENDING = 初始化狀態(tài)
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)");
}
}
// 2. 將AsyncTask狀態(tài)設(shè)置為RUNNING狀態(tài)
mStatus = Status.RUNNING;
// 3. 主線程初始化工作
onPreExecute();
// 4. 添加參數(shù)到任務(wù)中
mWorker.mParams = params;
// 5. 執(zhí)行任務(wù)
// 此處的exec = sDefaultExecutor = 任務(wù)隊列 線程池類(SerialExecutor)的對象
// ->>分析2
exec.execute(mFuture);
return this;
}
/**
* 分析2:exec.execute(mFuture)
* 說明:屬于任務(wù)隊列 線程池類(SerialExecutor)的方法
*/
private static class SerialExecutor implements Executor {
// SerialExecutor = 靜態(tài)內(nèi)部類
// 即 是所有實例化的AsyncTask對象公有的
// SerialExecutor 內(nèi)部維持了1個雙向隊列;
// 容量根據(jù)元素數(shù)量調(diào)節(jié)
final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
Runnable mActive;
// execute()被同步鎖synchronized修飾
// 即說明:通過鎖使得該隊列保證AsyncTask中的任務(wù)是串行執(zhí)行的
// 即 多個任務(wù)需1個個加到該隊列中;然后 執(zhí)行完隊列頭部的再執(zhí)行下一個,以此類推
public synchronized void execute(final Runnable r) {
// 將實例化后的FutureTask類 的實例對象傳入
// 即相當(dāng)于:向隊列中加入一個新的任務(wù)
mTasks.offer(new Runnable() {
public void run() {
try {
r.run();
} finally {
scheduleNext();->>分析3
}
}
});
// 若當(dāng)前無任務(wù)執(zhí)行,則去隊列中取出1個執(zhí)行
if (mActive == null) {
scheduleNext();
}
}
// 分析3
protected synchronized void scheduleNext() {
// 1. 取出隊列頭部任務(wù)
if ((mActive = mTasks.poll()) != null) {
// 2. 執(zhí)行取出的隊列頭部任務(wù)
// 即 調(diào)用執(zhí)行任務(wù)線程池類(THREAD_POOL_EXECUTOR)->>繼續(xù)往下看
THREAD_POOL_EXECUTOR.execute(mActive);
}
}
}
總結(jié):
- 執(zhí)行任務(wù)前,通過 任務(wù)隊列 線程池類(SerialExecutor)將任務(wù)按順序放入到隊列中;
通過同步鎖 修飾
execute()從而保證AsyncTask中的任務(wù)是串行執(zhí)行的
- 之后的線程任務(wù)執(zhí)行是 通過任務(wù)線程池類(THREAD_POOL_EXECUTOR) 進行的。
繼續(xù)往下分析:THREAD_POOL_EXECUTOR.execute()
/**
* 源碼分析:THREAD_POOL_EXECUTOR.execute()
* 說明:
* a. THREAD_POOL_EXECUTOR實際上是1個已配置好的可執(zhí)行并行任務(wù)的線程池
* b. 調(diào)用THREAD_POOL_EXECUTOR.execute()實際上是調(diào)用線程池的execute()去執(zhí)行具體耗時任務(wù)
* c. 而該耗時任務(wù)則是步驟2中初始化WorkerRunnable實例對象時復(fù)寫的call()
* 注:下面先看任務(wù)執(zhí)行線程池的線程配置過程,看完后請回到步驟2中的源碼分析call()
*/
// 步驟1:參數(shù)設(shè)置
//獲得當(dāng)前CPU的核心數(shù)
private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
//設(shè)置線程池的核心線程數(shù)2-4之間,但是取決于CPU核數(shù)
private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4));
//設(shè)置線程池的最大線程數(shù)為 CPU核數(shù)*2+1
private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
//設(shè)置線程池空閑線程存活時間30s
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());
}
};
//初始化存儲任務(wù)的隊列為LinkedBlockingQueue 最大容量為128
private static final BlockingQueue<Runnable> sPoolWorkQueue =
new LinkedBlockingQueue<Runnable>(128);
// 步驟2: 根據(jù)參數(shù)配置執(zhí)行任務(wù)線程池,即 THREAD_POOL_EXECUTOR
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);
// 設(shè)置核心線程池的 超時時間也為30s
threadPoolExecutor.allowCoreThreadTimeOut(true);
THREAD_POOL_EXECUTOR = threadPoolExecutor;
}
// 請回到步驟2中的源碼分析call()
至此,我們回到步驟2中的源碼分析call()
/**
* 步驟2的源碼分析:AsyncTask的構(gòu)造函數(shù)
*/
public AsyncTask() {
// 1. 初始化WorkerRunnable變量 = 一個可存儲參數(shù)的Callable對象
mWorker = new WorkerRunnable<Params, Result>() {
public Result call() throws Exception {
// 添加線程的調(diào)用標(biāo)識
mTaskInvoked.set(true);
Result result = null;
try {
// 設(shè)置線程的優(yōu)先級
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
// 執(zhí)行異步操作 = 耗時操作
// 即 我們使用過程中復(fù)寫的耗時任務(wù)
result = doInBackground(mParams);
Binder.flushPendingCommands();
} catch (Throwable tr) {
mCancelled.set(true);// 若運行異常,設(shè)置取消的標(biāo)志
throw tr;
} finally {
// 把異步操作執(zhí)行的結(jié)果發(fā)送到主線程
// 從而更新UI ->>分析1
postResult(result);
}
return result;
}
};
.....// 省略
}
/**
* 分析1:postResult(result)
*/
private Result postResult(Result result) {
@SuppressWarnings("unchecked")
// 創(chuàng)建Handler對象 ->> 源自InternalHandler類—>>分析2
Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
new AsyncTaskResult<Result>(this, result));
// 發(fā)送消息到Handler中
message.sendToTarget();
return result;
}
/**
* 分析2:InternalHandler類
*/
private static class InternalHandler extends Handler {
// 構(gòu)造函數(shù)
public InternalHandler() {
super(Looper.getMainLooper());
// 獲取的是主線程的Looper()
// 故 AsyncTask的實例創(chuàng)建 & execute()必須在主線程使用
}
@Override
public void handleMessage(Message msg) {
AsyncTaskResult<?> result = (AsyncTaskResult<?>) msg.obj;
switch (msg.what) {
// 若收到的消息 = MESSAGE_POST_RESULT
// 則通過finish() 將結(jié)果通過Handler傳遞到主線程
case MESSAGE_POST_RESULT:
result.mTask.finish(result.mData[0]); ->>分析3
break;
// 若收到的消息 = MESSAGE_POST_PROGRESS
// 則回調(diào)onProgressUpdate()通知主線程更新進度的操作
case MESSAGE_POST_PROGRESS:
result.mTask.onProgressUpdate(result.mData);
break;
}
}
}
/**
* 分析3:result.mTask.finish(result.mData[0])
*/
private void finish(Result result) {
// 先判斷是否調(diào)用了Cancelled()
// 1. 若調(diào)用了則執(zhí)行我們復(fù)寫的onCancelled()
// 即 取消任務(wù)時的操作
if (isCancelled()) {
onCancelled(result);
} else {
// 2. 若無調(diào)用Cancelled(),則執(zhí)行我們復(fù)寫的onPostExecute(result)
// 即更新UI操作
onPostExecute(result);
}
// 注:不管AsyncTask是否被取消,都會將AsyncTask的狀態(tài)變更為:FINISHED
mStatus = Status.FINISHED;
}
總結(jié)
- 任務(wù)線程池類
(THREAD_POOL_EXECUTOR)實際上是1個已配置好的可執(zhí)行并行任務(wù)的線程池 - 調(diào)用
THREAD_POOL_EXECUTOR.execute()實際上是調(diào)用線程池的execute()去執(zhí)行具體耗時任務(wù) - 而該耗時任務(wù)則是步驟2中初始化
WorkerRunnable實例對象時復(fù)寫的call()內(nèi)容 - 在
call()方法里,先調(diào)用 我們復(fù)寫的doInBackground(mParams)執(zhí)行耗時操作 - 再調(diào)用
postResult(result), 通過InternalHandler類 將任務(wù)消息傳遞到主線程;根據(jù)消息標(biāo)識(MESSAGE_POST_RESULT)判斷,最終通過finish()調(diào)用我們復(fù)寫的onPostExecute(result),從而實現(xiàn)UI更新操作
至此,關(guān)于AsyncTask的源碼 分析完畢,附上一份最終總結(jié):

9. 總結(jié)
- 本文介紹了多線程中的
AsyncTask的 工作原理 & 源碼分析,總結(jié)如下:


- 下一篇文章我將對講解
Android多線程的相關(guān)知識,感興趣的同學(xué)可以繼續(xù)關(guān)注Carson_Ho的簡書
Carson帶你學(xué)多線程系列
基礎(chǔ)匯總
Android多線程:基礎(chǔ)知識匯總
基礎(chǔ)使用
Android多線程:繼承Thread類使用(含實例教程)
Android多線程:實現(xiàn)Runnable接口使用(含實例教程)
復(fù)合使用
Android 多線程:AsyncTask使用教程(含實例講解)
Android 多線程:AsyncTask原理及源碼分析
Android多線程:HandlerThread使用教程(含實例講解)
Android多線程:HandlerThread原理及源碼分析
Android多線程:IntentService使用教程(含實例講解)
Android多線程:IntentService的原理及源碼分析
Android多線程:線程池ThreadPool全方位教學(xué)
相關(guān)使用
Android異步通信:這是一份全面&詳細(xì)的Handler機制學(xué)習(xí)攻略
Android多線程:手把手教你全面學(xué)習(xí)神秘的Synchronized關(guān)鍵字
Android多線程:帶你了解神秘的線程變量 ThreadLocal
歡迎關(guān)注Carson_Ho的簡書
不定期分享關(guān)于安卓開發(fā)的干貨,追求短、平、快,但卻不缺深度。
