在研究AsyncTask源碼之前,我們先通過一個例子來了解一下AsyncTask的用法,看其有哪些方法。
public class AsynActivity extends Activity implements OnClickListener{
Button btn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_asyn);
btn = (Button)findViewById(R.id.asyn);
btn.setOnClickListener(this);
}
@Override
public void onClick(View view) {
TestAsyn asyn = new TestAsyn();
asyn.execute();
//asyn.cancel(true);
Log.i("AsynActivity", String.valueOf(asyn.isCancelled()));
}
class TestAsyn extends AsyncTask<Void, Void, Result>{
@Override
protected void onPreExecute() {
Log.i("TestAsyn", "onPreExecute");
super.onPreExecute();
}
@Override
protected Result doInBackground(Void... params) {
Log.i("TestAsyn", "doInBackground");
//publishProgress(params);
//cancel(true);
return null;
}
@Override
protected void onPostExecute(Result result) {
Log.i("TestAsyn", "onPostExecute");
super.onPostExecute(result);
}
@Override
protected void onProgressUpdate(Void... values) {
Log.i("TestAsyn", "onProgressUpdate");
super.onProgressUpdate(values);
}
@Override
protected void onCancelled() {
Log.i("TestAsyn", "onCancelled");
super.onCancelled();
}
@Override
protected void onCancelled(Result result) {
Log.i("TestAsyn", "onCancelled");
super.onCancelled(result);
}
}
}
運行結果:
從結果我們可以看出,在調用execute()後,首先執行的是onPreExecute,然後是doInBackground,最後是onPostExecute方法,這三個方法在調用execute
之後會自動執行。然後我們將onClick方法中的cancel()註釋去掉,運行結果輸出:
從結果我們可以知道,在調用cancel()方法之後,所有未被執行的方法都不會被執行了,如果doInBackground沒有被執行,那麼doInBackground和
onPostExecute都不會被執行了。如果doInBackground已經被執行了,onPostExecute還未被執行,那麼onPostExecute還會被被執行嗎?要驗證一
下就在doInBackground方法中調用cancel()方法,執行的結果就是onPostExecute方法沒有輸出,也就是其沒有被執行。從上面這個結果中我們還知
道,在調用cancel()方法後,兩個onCancelled()方法都會被執行。
有沒有發現onProgressUpdate方法一直都沒有執行,爲什麼呢?因爲需要在doInBackground方法中調用publishProgress方法,調用這個方法之後
onProgressUpdate方法就會自動被執行。你可以將這個例子中的publishProgress前的註釋去掉,然後運行就會發現onProgressUpdate方法就被執
行了。
使用知道以後,下面我們就來分析一下他的源碼:我取出了源碼中的一些無用的方法以及註釋,剩下了210行左右的代碼,下面我將整個代碼貼出來
public abstract class AsyncTask<Params, Progress, Result> {
private static final String LOG_TAG = "AsyncTask";
private static final int CORE_POOL_SIZE = 5;
private static final int MAXIMUM_POOL_SIZE = 128;
private static final int KEEP_ALIVE = 1;
private static final ThreadFactory sThreadFactory = new ThreadFactory() {
private final AtomicInteger mCount = new AtomicInteger(1);//原子類,消除synchronized關鍵字
public Thread newThread(Runnable r) {
return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());
}
};//創建線程工廠對象
private static final BlockingQueue<Runnable> sPoolWorkQueue =
new LinkedBlockingQueue<Runnable>(10);//同步隊列
public static final Executor THREAD_POOL_EXECUTOR
= new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,
TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);//創建線程池
private static final int MESSAGE_POST_RESULT = 0x1;
private static final int MESSAGE_POST_PROGRESS = 0x2;
//定義handler,他的實現也使用了handler額
private static final InternalHandler sHandler = new InternalHandler();
private static volatile Executor sDefaultExecutor = new SerialExecutor();
private final WorkerRunnable<Params, Result> mWorker;//定義Callable接口對象,執行結果的返回就跟這個對象的屬性有關
private final FutureTask<Result> mFuture;//定義FutureTask對象
public enum Status {PENDING,RUNNING,FINISHED,}//枚舉對象,3種狀態
private volatile Status mStatus = Status.PENDING; //初始化狀態爲pending
private final AtomicBoolean mTaskInvoked = new AtomicBoolean();//原子對象
//構造方法
public AsyncTask() {
mWorker = new WorkerRunnable<Params, Result>() {
public Result call() throws Exception {
mTaskInvoked.set(true);
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
return postResult(doInBackground(mParams));
}
};//創建Callable接口對象
mFuture = new FutureTask<Result>(mWorker) {
@Override
protected void done() {
try {
final Result result = get();
postResultIfNotInvoked(result);
} 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);
} catch (Throwable t) {
throw new RuntimeException("An error occured while executing doInBackground()", t);
}
}
};//將Callable接口對象mWorker作爲參數傳遞給FutureTask,這些都是java類庫中的一些基本使用,不瞭解的好好把Java編程思想看完
}
private void postResultIfNotInvoked(Result result) {
final boolean wasTaskInvoked = mTaskInvoked.get();
if (!wasTaskInvoked) {
postResult(result);
}
}
private Result postResult(Result result) {
Message message = sHandler.obtainMessage(MESSAGE_POST_RESULT,
new AsyncTaskResult<Result>(this, result));
message.sendToTarget();
return result;
}
//AsyncTask類中能夠被重寫的方法
protected abstract Result doInBackground(Params... params);
protected void onPreExecute() {}
@SuppressWarnings({"UnusedDeclaration"})
protected void onPostExecute(Result result) {}
@SuppressWarnings({"UnusedDeclaration"})
protected void onProgressUpdate(Progress... values) {}
@SuppressWarnings({"UnusedParameters"})
protected void onCancelled(Result result) {
onCancelled();
}
protected void onCancelled() {}
//下面這些方法都不能夠被重載,因爲是final類型的。
public final boolean isCancelled() {
return mFuture.isCancelled();
}
public final boolean cancel(boolean mayInterruptIfRunning) {
return mFuture.cancel(mayInterruptIfRunning);
}
public final Result get() throws InterruptedException, ExecutionException {
return mFuture.get();
}
public final Result get(long timeout, TimeUnit unit) throws InterruptedException,
ExecutionException, TimeoutException {
return mFuture.get(timeout, unit);
}
//AsyncTask調用的三個方法,
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);
}
public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,Params... params) {
if (mStatus != Status.PENDING) {
switch (mStatus) {
case RUNNING:
throw new IllegalStateException("");
case FINISHED:
throw new IllegalStateException("");
}
}
mStatus = Status.RUNNING;
onPreExecute();
mWorker.mParams = params;
exec.execute(mFuture);
return this;
}//看見沒第一個方法調用其實也是executeOnExecutor,那爲什麼不直接調用呢?因爲在這個方法中我們可以自定義線程執行器Executor
public static void execute(Runnable runnable) {
sDefaultExecutor.execute(runnable);
}
protected final void publishProgress(Progress... values) {
if (!isCancelled()) {
sHandler.obtainMessage(MESSAGE_POST_PROGRESS,
new AsyncTaskResult<Progress>(this, values)).sendToTarget();
}
}
private void finish(Result result) {
if (isCancelled()) {
onCancelled(result);
} else {
onPostExecute(result);
}
mStatus = Status.FINISHED;
}
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;
}
}
}
@SuppressWarnings({"RawUseOfParameterizedType"})
private static class AsyncTaskResult<Data> {
final AsyncTask mTask;
final Data[] mData;
AsyncTaskResult(AsyncTask task, Data... data) {
mTask = task;
mData = data;
}
}
private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> {
Params[] mParams;
}
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();//真正執行Callable中run方法的地方
} finally {
scheduleNext();
}
}
});//新建一個Runnable對象,在run方法中執行參數Runnable對象的run方法,然後將其放入數組雙端隊列mTasks中
if (mActive == null) {
scheduleNext();
}
}
protected synchronized void scheduleNext() {
if ((mActive = mTasks.poll()) != null) {
THREAD_POOL_EXECUTOR.execute(mActive);//將任務添加到線程池中
}
}
}
}
上面就是AsyncTask類全部代碼,其他無用的代碼和註釋被我去掉了。我的版本爲4.03。下面我們就來根據執行的順序來進行源碼分析。
一、從上面代碼我們知道,創建AsyncTask對象時,會創建一個ThreadPoolExecutor的線程池,那些隊列,線程工廠都是作爲參數傳遞
給這個線程池的,所以不用管,你只要知道這個線程池的相關知識就行。
二、創建了一個枚舉類型Status,其中具有3種狀態,聲明瞭一個枚舉對象mStatus,並初始化狀態爲PENDING。
三、創建了Handler,以及一個默認的線程執行器sDefaultExecutor,之所以爲默認,那就證明其實這個線程執行器我們自己可以自定義的
。嗯,所有的準備工作做好了,接下來我們就來看構造方法。
在構造方法中,實例化了mWorker對象和mFuture對象,在mWoker實例中的call方法中,我們可以看到doInBackground方法就是在這裏
被調用的,從這裏我們可以看出doInBackground方法其實是在子線程中被執行的。mFuture在實例化過程中,mWoker作爲參數傳入,並
且mFuture重寫了done()方法,通過查看Java API可以知道,這個方法主要用來查詢Task是否被取消,在這裏獲取查詢的結果。
這樣構造方法就分析完全了,對象初始化就完成了。接下來我們根據調用步驟來進行分析。
一、從上面的實例中我們可以知道,AsyncTask類有三個啓動方法,從源碼中我們可以知道這三個方法的差異:
1、execute(Params... params) 這個方法其實調用就是第二個方法。
2、executeOnExecutor 既然第一個方法調用是第二個方法,爲什麼不將這兩個方法和爲一個方法,理由就是:第一個方法不能自定義線程
執行器,而第二個方法能夠自定義線程執行器。
3、execute(Runnable runnable)。這個方法就是自定義子線程,源碼提供的mFuture,以及mWoker對象都無用了,這些東西都要自己去實
現,但是使用的還是源碼默認的線程執行器。
那些需要自定義的方法我就不進行分析了,主要分析系統默認調用的方法,所以我們現在拿第一個方法爲引導來進行逐步分析。
步驟分析:
步驟一、execute()方法調用後,將默認的線程執行器對象sDefaultExecutor傳入了進去,調用executeOnExecutor方法,查看
executeOnExecutor方法。
步驟二、在executeOnExecutor方法中,首先對任務的狀態進行了判斷,如果不是初始狀態則拋出異常,這證明execute()方法只能被執行一次
多次執行則無效。判斷之後將任務狀態設置爲RUNNING態,執行onPreExecute()方法,從這裏可以看出來,onPreExecute()方法其實還是在
主線程中被執行的,他並沒有放到子線程中去執行。然後調用線程執行器將任務對象mFuture進行提交。
步驟三、查看任務執行器的實行類SerialExecutor,從源碼中我們可以看到,首先創建一個雙端隊列數組mTasks,提交一個Runnable對象放
到這個隊列中,並且將任務放到這個Runnable對象的run方法中來執行。提交到mTasks中後,再從隊列中取出,將取出的放入到線程池中進
行執行。這樣任務就開始執行了。
步驟四、任務開始執行後,在線程池中執行的是doInBackground方法,doInBackground方法執行完成後返回結果作爲postResult的參數,接
下來我們看一看postResult方法。
步驟五、doInBackground方法返回的結果作爲參數傳進來後,在postResult方法中利用hanlder發送了一個MESSAGE_POST_RESULT msg
我們在handler中可以看到,MESSAGE_POST_RESULT消息接收器中,收到消息後就執行了finish(result.mData[0])方法,接下來我們來看一
下finish方法,在這個方法中調用isCancelled()來判斷任務是否被取消,如果被取消則在onCancelled方法中返回結果,否則調用onPostExecute
方法。
至此AsyncTask的執行過程就已經分析完了,接下來我們就來看onProgressUpdate的執行過程,我們知道要onProgressUpdate執行就必須在
doInBackground方法中調用publishProgress方法才行,那我們就來看publishProgress方法的代碼,從他的代碼中我們可以看出,他利用
handler發送了一個MESSAGE_POST_PROGRESS的消息,那麼來看handler接收器,從handler接收器中可以看到,在這裏調用了
onProgressUpdate方法了。這就是onProgressUpdate方法的執行過程。從他的調用過程中我們可以看到,這個方法其實是在主線程中執行的
這也是爲什麼能夠在這個方法中進行UI更新的操作。
總結:創建AsyncTask對象,會創建一個線程池,調用excute方法啓動任務後,doInBackground會在線程池中執行,其他的方法都是在主線程
中被執行。所以所有關於UI的操作都不能在doInBackground中進行操作。
接下來的任務就是怎樣來調用需要自定義一些數據結構的方法了。下篇博文見吧。