AsyncTask這個類用的比較多,平時做項目時,一般用在文件下載這一塊多比較多。其使用起來還算方便,實現根本的原理還是Thread + Handler。這篇文章就來談談AsyncTask的基本使用以及其原理實現,同時說說其和Handler的關係。
1、AsyncTask的基本使用
使用AsyncTask都得實現一個AsyncTask的子類,並在其中重載AsyncTask的一些方法(publishProgress不需要重載,也不能重載,這裏放在一起講),下面就來對這些方法做一些介紹。
protected void onPreExecute()
這個方法主要是在異步執行前去執行一些初始化的工作,因爲onPreExecute方法實際上是執行在主線程,所以可以在其中執行一些界面操作。
protected abstract Result doInBackground(Params... params)
這個放是一個異步方法了,也就是說它不是在主線程中執行,故不能再其中執行界面操作,但是由於其是異步方法所以一般在方法體內執行一些耗時操作,不如文件下載等。
protected final void publishProgress(Progress... values)
這個方法用來在doInBackground方法的中拋出進度數據,並通過傳遞Handler消息,將數據傳到後面要講的onProgressUpdate方法中。
protected void onProgressUpdate(Progress... values)
上面說了,這個方法接收來自publishProgress方法傳遞過來的數據,並且由於通過Handler機制接收的數據,所以onProgressUpdate這個方法實際是在主線程中執行的,所以能在其中進行界面操作,一般我們在這個方法體中操作進度條。
protected void onPostExecute(Result result)
doInBackground方法執行完畢後會調用改方法,並且由於doInBackground也是通過Handler機制給onPostExcute傳遞數據,所以在這個方法中也可以操作界面。
protected void onCancelled()
protected void onCancelled(Result result)
這兩個方法沒啥好說的,也就是取消doInBackground的執行,進而阻斷整個異步過程。
另外我們看看AsyncTask類的聲明
public abstract class AsyncTask<Params, Progress, Result>
對比這裏的泛型參數和以上幾個方法的參數,我們很容易知道,
Params是doInBackground接收的參數類型
Progress是publishProgress以及onProgressUpdate兩個方法接收的參數類型
Result是onPostExecute以及onCancelled接收的參數類型
2、AsyncTask工作原理說明
第一小節說明了AsyncTask子類需要重載(或者可以重載)的一些方法,當定義好子類後便可通過子類的實例執行execute方法便可以啓動任務運行。
execute方法會執行到下面方法中
@MainThread
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方法,這就是我們前面說的onPreExecute執行在主線程中的原因。接着會通過一個線程管理器來執行mFuture,這個mFuture是一個Runable子類實例。
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);
}
};
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);
}
}
};
而exec.execute(mFuture)方法會執行到FutureTask.run方法,在執行run方法中有以下代碼
try {
result = c.call();
ran = true;
} catch (Throwable ex) {
result = null;
ran = false;
setException(ex);
}
if (ran)
set(result);
這個代碼中的c.call()方法調用上面mWorker中的call方法,並在其中執行doInBackground並返回result,然後run方法中接着調動set(result)將result值賦給FutureTask.outcome對象。
run方法最終會執行會mFuture的done方法中來,再看done方法裏的postResultIfNotInvoked(get())方法這裏有個get()方法獲取FutureTask.outcome對象(也就是doInBackground方法返回的result值),然後postResultIfNotInvoked方法會執行到以下postResult方法
private Result postResult(Result result) {
@SuppressWarnings("unchecked")
Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
new AsyncTaskResult<Result>(this, result));
message.sendToTarget();
return result;
}
到這裏我們看到使用了Handler機制來傳遞消息了,那麼接受消息的Handler呢就是下面這位大哥了
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;
}
}
}
它會根據傳過來的MESSAGE_POST_RESULT去執行finish方法,我們再跟一下
private void finish(Result result) {
if (isCancelled()) {
onCancelled(result);
} else {
onPostExecute(result);
}
mStatus = Status.FINISHED;
}
當沒有執行cancel操作時,finish方法會執行onPostExecute方法並獲取doInBackground傳遞過來的值。
以上代碼我們說清楚了onPreExecute、doInBackground、onPostExecute這幾個方法。
接着我們看看當調用publishProgress方法時,執行如下代碼
@WorkerThread
protected final void publishProgress(Progress... values) {
if (!isCancelled()) {
getHandler().obtainMessage(MESSAGE_POST_PROGRESS,
new AsyncTaskResult<Progress>(this, values)).sendToTarget();
}
}
我們看到這裏還是使用了Handler機制,並傳MESSAGE_POST_PROGRESS消息,對比上面的Handler,我們知道Handler接受到消息後會執行onProgressUpdate方法。
這裏便講清了publishProgress方法同onProgressUpdate方法之間的關係。
最後,當在執行過程中進行cancel操作時,會在執行上面的finish方法是執行到onCancelled方法中去而不是執行onPostExecute方法。
private void finish(Result result) {
if (isCancelled()) {
onCancelled(result);
} else {
onPostExecute(result);
}
mStatus = Status.FINISHED;
}
這樣就說清了onCancelled方法。
3、參考文獻
1、詳[解Android中AsyncTask的使用](http://blog.csdn.net/liuhe688/article/details/6532519)