android源碼分析-AsyncTask
我們一般創(chuàng)建一個AsyncTask的任務(wù)代碼如下:
AsyncTask<String , String , String> task = new AsyncTask<String, String, String>() {
@Override
protected void onPreExecute() {
//UI線程,線程開始前執(zhí)行,一般用于初始化操作
super.onPreExecute();
}
@Override
protected String doInBackground(String... params) {
//子線程后臺線程執(zhí)行操作
return null;
}
@Override
protected void onProgressUpdate(String... values) {
//UI線程,進度更新,通過在doInBackground方法中調(diào)用publishProgress傳遞過來更新進度
super.onProgressUpdate(values);
}
@Override
protected void onPostExecute(String s) {
//UI線程,后臺操作執(zhí)行完畢執(zhí)行
super.onPostExecute(s);
}
};
task.execute();
下面開始分析源碼:
流程先看AsyncTask的構(gòu)造方法:
public AsyncTask() {
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);
}
}
};
}
1.代碼開始看可能有些難懂.其實說明一下就好很多了,WorkerRunnable是自定義的一個抽象類.里邊先定義了進程的線程優(yōu)先級(跟我們要講的暫時沒啥關(guān)系),又實現(xiàn)了doInBackground()方法,這就發(fā)現(xiàn)了doInBackground就是我們demo上new AsyncTask()必須重寫的方法,AsyncTask中doInBackground()方法有注解@WorkerThread,說明他在工作線程.
2.然后return了postResult(result);,而且在new FutureTask中也調(diào)用了postResultIfNotInvoked(get());,而這個方法最后也是調(diào)用了postResult(result),所以來繼續(xù)跟蹤這個方法:
private Result postResult(Result result) {
@SuppressWarnings("unchecked")
Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,new AsyncTaskResult<Result>(this, result));
message.sendToTarget();
return result;
}
看到了熟悉的老朋友Message,然后有個方法message.sendToTarget();,這個是Message的方法,之前http://m.itdecent.cn/p/1e5f34f6635e文檔中有說過.
然后繼續(xù)看getHandler(),這個不是Handler的方法,我們可以追蹤這個方法"
private static Handler getHandler() {
synchronized (AsyncTask.class) {
if (sHandler == null) {
sHandler = new InternalHandler();
}
return sHandler;
}
}
看到了sHandler = new InternalHandler();說明重點代碼就在InternalHandler()類:
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;
}
}
}
根據(jù)消息類型判斷是否結(jié)束如果結(jié)束就走finish方法.
這里我們又看到了另一個熟悉的名字onProgressUpdate(),用來更新進度用的實現(xiàn)方法.如果沒結(jié)束就走這個分支.
看一下上邊說的finish方法:
private void finish(Result result) {
if (isCancelled()) {
onCancelled(result);
} else {
onPostExecute(result);
}
mStatus = Status.FINISHED;
}
這個就很好理解了,取消就調(diào)用取消的回調(diào),結(jié)束就調(diào)用結(jié)束的回調(diào).
我們還有個回調(diào)方法沒找到,我們看一下:
@WorkerThread
protected final void publishProgress(Progress... values) {
if (!isCancelled()) {
getHandler().obtainMessage(MESSAGE_POST_PROGRESS,new AsyncTaskResult<Progress>(this, values)).sendToTarget();
}
}
這個調(diào)用應(yīng)該是在doInBackground()方法中.通知onProgressUpdate()刷新進度.
看到了這里也是發(fā)出了一個Message.就應(yīng)該在InternalHandler中的刷新進度的分支接受到消息.
下面看execute()方法:
通過跟蹤發(fā)現(xiàn)調(diào)用了executeOnExecutor(sDefaultExecutor, params);:
@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;
}
這里有個回調(diào)方法onPreExecute()就是在執(zhí)行doInBackground()前在主線程執(zhí)行的方法.
然后把參數(shù)賦給了mWorker.mParams,然后執(zhí)行了exec.execute(mFuture);,這句就是讓線程執(zhí)行任務(wù)的關(guān)鍵代碼.
這個類點不進去了,但是我們找到了另外一個execute(runnable)的方法,跟蹤看一下有個sDefaultExecutor.execute(runnable);,
然后看一下sDefaultExecutor是什么鬼.繼續(xù)找,找到了SERIAL_EXECUTOR,看看SERIAL_EXECUTOR是什么鬼吧.
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);
}
}
}
這里有兩個類execute和scheduleNext()方法,作用是把任務(wù)反倒隊列中執(zhí)行.
mTasks.offer方法是把任務(wù)放到隊列末尾,THREAD_POOL_EXECUTOR.execute(mActive)應(yīng)該是從頭部取任務(wù)執(zhí)行.
我覺得這的代碼應(yīng)該是新建ArrayDeque<Runnable> 線程隊列,然后加了同步鎖,執(zhí)行了run開啟線程,在結(jié)束的時候從線程池取出線程.
這樣整個異步任務(wù)就執(zhí)行完了.
總結(jié)
通過構(gòu)造方法,實現(xiàn)了mWorker和mFuture(線程池類),先實現(xiàn)了doInBackground()告訴程序開啟線程做什么,然后調(diào)用了postResult(),這個方法建立了Handler和Message系列,并且在Handler中接收結(jié)束和更新進度的msg.(現(xiàn)在有個問題mWorker中return的postResult()時機問題,為什么要在這里調(diào)用結(jié)束的方法?可能是mFuture里邊做的,畢竟最后mWorker也是mFuture的參數(shù),這里也請看到的大神們指導(dǎo)一下).
execute()方法在調(diào)用exec.execute(mFuture);前實現(xiàn)了onPreExecute()調(diào)用了線程開啟的回調(diào)方法.接著新建ArrayDeque<Runnable> 線程隊列,把mFuture任務(wù)添加到隊尾,線程池從隊列頭取出任務(wù)執(zhí)行.(可見Asynctask的任務(wù)是逐個完成的),這樣異步任務(wù)就實現(xiàn)了.