概述
AsyncTask類內部封裝了Handler和線程池。可以簡化其他線程對UI的操作。
AsyncTask是一個抽象類,我們需要創建子類去繼承它,並且重組一些方法。
參數
-
Params:指定傳給任務執行時的參數的類型
-
Progress:指定後臺任務執行時將任務進度返回給UI線程的參數類型
-
Result:指定任務完成後返回的結果的類型
方法
-
onPreExecute():這個方法在UI線程調用,用於在任務執行前做一些初始化操作,如在界面上顯示加載進度控件
-
doInBackground:在onPreExecute()結束之後立即在後臺線程調用,用於耗時操作。在這個方法中可調用publishProgress方法返回任務的執行進度
-
onProgressUpdate:在doInBackground調用publishProgress後被調用,工作在UI線程
-
onPostExecute:後臺任務結束後被調用,工作在UI線程
源碼
3.0前的AsyncTask
- 線程池使用的是ThreadPoolExecutor,核心線程數爲5個,最大線程數爲128,非核心線程空閒等待新任務的最長時間爲1s。
- 阻塞隊列是LinkedBlockQueue,他的容量是10
- 缺點:線程池最大線程數是128,加上阻塞隊列的10個任務,最多容納138個任務。
3.0後的AsyncTask
這個類的實現,主要有線程池以及Handler兩部分。
構造方法:
- WorkerRunnable實現了Callable接口,並實現了它的call方法,在call方法中調用了doInBackground(mParams)來處理任務並得到結果,並最終調用postResult將結果投遞出去。
- FutureTask是一個可管理的異步任務,它實現了Runnable和Futrue這兩個接口。它可以包裝Runnable和Callable,並提供給Executor執行。
- WorkerRunnable作爲參數傳遞給了FutureTask。
執行一個任務的時候,調用的是execute方法:
public final AsyncTask execute(Params... params){
return executeOnExecutor(sDefaultExecutor, params);
}
public final AsyncTask 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
onPreExecute();
mWorker.mParams = params;
exec.execute(mFuture);
return this;
}
概述一下
- 先檢測任務是否已經執行或者執行結束。然後將任務標記爲running。
- 開始執行onPreExecute方法。
- 接着把參數賦值給mWorker對象,他是一個Callable對象,最終會被包裝爲FutureTask。
- 接下來會調用exec的execute方法,並將mFuture也就是前面講到的FutureTask傳進去。
- exec是傳進來的參數sDefaultExecutor,它是一個串行的線程池 SerialExecutor,代碼如下
概述一下:
- 當調用SerialExecutor 的execute方法時,會將FutureTask加入到mTasks中。
- 當任務執行完或者當前沒有活動的任務時都會執行scheduleNext方法,它會從 mTasks 取出 FutureTask 任務並交由 THREAD_POOL_EXECUTOR 處理。
- 從這裏可以看出SerialExecutor是串行執行的。註釋2處執行了FutureTask的run方法,它最終會調用WorkerRunnable的call方法。
postReult方法:
- postResult方法中會創建Message,將結果賦值給這個Message。
- 通過getHandler方法得到Handler,並通過這個Handler發送消息。
接收到MESSAGE_POST_RESULT消息後會調用AsyncTask的finish方法:
- 如果AsyncTask任務被取消了,則執行onCancelled方法,否則就調用onPostExecute方法。
線程池SerialExecutor主要用來處理排隊,將任務串行處理。在SerialExecutor中調用 scheduleNext 方法時,將任務交給 THREAD_POOL_EXECUTOR。
THREAD_POOL_EXECUTOR同樣是一個線程池,用來處理任務
- THREAD_POOL_EXECUTOR 指的就是 threadPoolExecutor,其核心線程和線程池允許創建的最大線程數都是由CPU的核數來計算出來的。
- 採用的阻塞隊列仍舊是LinkedBlockingQueue,容量爲128。
小結
- Android 3.0及以上版本用SerialExecutor作爲默認的線程,它將任務串行地處理,保證一個時間段只有一個任務執行;
- 而Android 3.0之前的版本是並行處理的。
- Android 3.0之前版本的缺點在Android 3.0之後的版本中也不會出現,因爲線程是一個接一個執行的,不會出現超過任務數而執行飽和策略的情況。
- 如果想要在Android 3.0及以上版本使用並行的線程處理,可以使用如下的代碼:
asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,"");