Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android-AsyncTask源碼分析

Android-AsyncTask源碼分析

編輯:關於Android編程

AsyncTask異步任務類,允許在UI線程中進行後台操作和發布結果到UI線程中,一般使用多操作中,這個類的基本用法可以參照博主寫的另一邊博文http://blog.csdn.net/nzsdyun123/article/details/22215589這裡有講述AsyncTask的基本用法,今天我也按照上篇分析Handler機制那樣帶領大家來分析下AsyncTask的流程。

我們一般是這樣來開始啟動AsyncTask的:

MyAsyncTask myAsyncTask = new MyAsyncTask();

myAsyncTask.execute(path);

這裡MyAysncTask是AysncTask的子類,這裡我們使用AsyncTask的時候也是一般繼承AysncTask類,重寫其方法,我們查看AysncTask的源碼發現:

/**

*

AsyncTask enables proper and easy use of the UI thread. This class allows to

* perform background operations and publish results on the UI thread without

* having to manipulate threads and/or handlers.

*

*

AsyncTask is designed to be a helper class around {@link Thread} and {@link Handler}

* and does not constitute a generic threading framework. AsyncTasks should ideally be

* used for short operations (a few seconds at the most.) If you need to keep threads

* running for long periods of time, it is highly recommended you use the various APIs

* provided by the java.util.concurrent pacakge such as {@link Executor},

* {@link ThreadPoolExecutor} and {@link FutureTask}.

AsyncTask是後台UI線程,通過發布結果到UI線程中,同時這裡也給我們介紹了AsyncTask被設計成Thread和Handler的一個助手類,適用於短時的線程操作,長時的線程操作被推薦適用線程池ThreadPoolExecutor來解決,及其他的一些基礎用法等,從這裡的簡介中,提到AsyncTask被設計成Thread和Handler的一個助手類?我們這時就要想AsyncTask是不是對Thread+Handler的一個封裝?答案是這樣嗎?我們帶著疑問來分析:

當我們調用myAsyncTask.execute(path);這語句時,這時AsyncTask就開始正式工作了。我們來進入源碼分析這句:

public final AsyncTask execute(Params... params) {

return executeOnExecutor(sDefaultExecutor, params);

}

這裡函數被設計成接收三個泛型數據類型的類,同時參數被設計成可變參數,可以根據實際需求動態的傳入參數的個數。我們接著看跟蹤 return executeOnExecutor(sDefaultExecutor, params);

public final AsyncTask executeOnExecutor(Executor exec,

Params... params) {

if (mStatus != Status.PENDING) {//尚未創建AsyncTask

switch (mStatus) {

case RUNNING://有AsyncTask正在後台運行,拋出異常

throw new IllegalStateException("Cannot execute task:"

+ " the task is already running.");

case FINISHED://有AsyncTask任務已完成

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;

}

從上述分析可以知道當前UI線程的AsyncTask對象不能多次調用execute方法,關鍵的是我們看這幾句

onPreExecute();

mWorker.mParams = params;

exec.execute(mFuture);

追蹤onPreExecute();可以發現這是一個空實現方法:

/**

* Runs on the UI thread before {@link #doInBackground}.

*

* @see #onPostExecute

* @see #doInBackground

*/

protected void onPreExecute() {

}

子類可以重寫它,運行在UI線程,在doInBackground方法之前,從這裡我們可以知道,既然onPreExecute函數運行在UI線程中,所以我們可以在這做些資源的初始化的工作。接著來分析 mWorker.mParams = params;這句是將參數賦值給mWorker對象的參數。所以我們追蹤mWorker對象發現:

private final WorkerRunnable mWorker;

private final FutureTask mFuture;

它是AsyncTask的類類型對象,那WorkerRunnable到底是什麼呢?追蹤源碼可知:

private static abstract class WorkerRunnable implements Callable {

Params[] mParams;

}

它是一個抽象類,實現了Callable回調接口,用於從不同的線程來獲取結果Result,OK,我們接著分析:

exec.execute(mFuture);從executeOnExecutor函數聲明中可以看出exec是Executor的對象,Excutor?哇,這不就是線程池的運用嘛(線程池知識這裡不講解),這裡簡單講下Excutor,Excutor是一個接口,此接口提供一種將任務提交與每個任務將如何運行的機制(包括線程使用的細節、調度等)分離開來的方法。簡單講就是方便線程的創建和使用。那麼exec.execute(mFuture);就是執行線程,那這個mFuture肯定是一個Runnable或者實現Runnable接口的類,追蹤mFuture:

private final FutureTask mFuture;

FutureTask?這又是什麼呢?我們查看JDK幫助文檔可知:

public class FutureTask

extends Object

implements RunnableFuture

它是繼承了Object對象,實現RunnableFuture接口的類,當然RunnableFuture實現了Runnable接口,果不其然,由JDK可知

FutureTask是一個可取消的異步計算。利用開始和取消計算的方法、查詢計算是否完成的方法和獲取計算結果的方法。簡單來講就是獲取提供一些方法來開始和取消線程,同時可以獲取線程運行後的結果。那麼FutureTask和WorkerRunnable對象又是什麼時候開始創建的呢?追蹤可以發現它們是在我們創建AsyncTask對象時就給我們創建好了:

/**

* Creates a new asynchronous task. This constructor must be invoked on the UI thread.

*/

public AsyncTask() {

mWorker = new WorkerRunnable() {//創建WorkerRunnable,並實現Callable接口方法call

public Result call() throws Exception {

mTaskInvoked.set(true);//設置標志值

Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);//設置線程優先級

//noinspection unchecked

return postResult(doInBackground(mParams));//根據外部傳入的參數調用doInBackground方法,並將結果傳給postResult函數

}

};

mFuture = new FutureTask(mWorker) {

//創建FutureTask對象,重寫done方法

@Override

protected void done() {

try {

postResultIfNotInvoked(get());//等到線程執行完成,通過get方法獲取線程運行後的結果,傳給postResultIfNotInvoked方法

} catch (InterruptedException e) {

android.util.Log.w(LOG_TAG, e);

} catch (ExecutionException e) {

throw new RuntimeException("An error occured while executing doInBackground()",

e.getCause());

} catch (CancellationException e) {

postResultIfNotInvoked(null);

}

}

};

}

原來這兩個對象在AsyncTask類創建的時候就給預先創建好了,前面說到WorkerRunnable是一個實現了Runnable接口的類,當系統執行到exec.execute(mFuture);這句時,這時就會執行線程裡的WorkerRunnable的方法,這裡們可以看到,AsyncTask的設計者巧妙的使用回調,將需要在線程中運行的語句又交到了我們開發應用者手上,我們查看doInBackground(mParams)就可以知道:

protected abstract Result doInBackground(Params... params);

這是一個抽象的方法,我們子類可以實現它,當然這些語句會運行在另一個線程中,Ok這時我們查看postResult和postResultIfNotInvoked方法:

private void postResultIfNotInvoked(Result result) {

final boolean wasTaskInvoked = mTaskInvoked.get();

if (!wasTaskInvoked) {

postResult(result);

}

}

postResultIfNotInvoked方法最後也是調用postResult方法:

private Result postResult(Result result) {

@SuppressWarnings("unchecked")

Message message = sHandler.obtainMessage(MESSAGE_POST_RESULT,

new AsyncTaskResult(this, result));

message.sendToTarget();

return result;

}

從這裡可以看出,向sHandler所在的線程發送一個消息,並將線程運行後的結果回傳過去,ok,這裡我們分析sHandler對象的類:

private static final InternalHandler sHandler = new InternalHandler();

private static class InternalHandler extends Handler {

@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;

}

}

}

從上面可以知道,此Handler類接收兩個消息:MESSAGE_POST_RESULT線程執行完畢後消息,MESSAGE_POST_PROGRESS進度更新消息

result.mTask.finish(result.mData[0]);

我們從這句語句找到finish方法:

private void finish(Result result) {

if (isCancelled()) {

onCancelled(result);

} else {

onPostExecute(result);

}

mStatus = Status.FINISHED;

}

要麼是調用 */

@SuppressWarnings({"UnusedParameters"})

protected void onCancelled(Result result) {

onCancelled();

}

onCancelled來取消AysncTask,不然就是等待線程運行完成後,提交給onPostExecute(result);方法處理:

@SuppressWarnings({"UnusedDeclaration"})

protected void onPostExecute(Result result) {

}

所以,我們可以在子類中重寫onPostExecute這個方法時,獲取其結果,而MESSAGE_POST_PROGRESS消息是將結果交於onProgressUpdate(result.mData);處理:

@SuppressWarnings({"UnusedDeclaration"})

protected void onProgressUpdate(Progress... values) {

}

這裡一般是我們重寫時獲取進度來進行進度條更新的,那這個消息MESSAGE_POST_PROGRESS又從哪裡向handler發送的呢?我們繼續追查:

protected final void publishProgress(Progress... values) {

if (!isCancelled()) {

sHandler.obtainMessage(MESSAGE_POST_PROGRESS,

new AsyncTaskResult(this, values)).sendToTarget();

}

}

在這個方法裡發送的,這就我們可以解釋的同,為什麼我們調用

publishProgress的時候,可以在onProgressUpdate接收結果並更新UI,publishProgress是通過handler向創建AsyncTask所在的線程中發送消息並將結果回傳過去的。到目前為止,AsyncTask的源碼分析就分析的差不多了,這也驗證了我們剛開始的猜想,AsyncTask是對Thread+Handler的封裝,當然這裡不是直接使用Thread的,而已使用靜態線程池來進行的,這個查看AsyncTask的各個屬性聲明就可以知道,當然這也帶來了一些限制,那就是線程數不能創建太多。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved