AsyncTask源碼分析,asynctask源碼
關於AsyncTask的用法可以參看前面一篇部落格《AsyncTask實現斷點續傳》,本文只解析AsyncTask的原始碼。 AsyncTask.execute方法:
1 public final AsyncTask<Params, Progress, Result> execute(Params... params) {2 return executeOnExecutor(sDefaultExecutor, params);3 }execute方法裡面直接調用了executeOnexecute方法。 AsyncTask.executeOnexecute方法:
1 public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec, 2 Params... params) { 3 if (mStatus != Status.PENDING) { 4 switch (mStatus) { 5 case RUNNING: 6 throw new IllegalStateException("Cannot execute task:" 7 + " the task is already running."); 8 case FINISHED: 9 throw new IllegalStateException("Cannot execute task:"10 + " the task has already been executed "11 + "(a task can be executed only once)");12 }13 }14 mStatus = Status.RUNNING;15 onPreExecute();16 mWorker.mParams = params;17 exec.execute(mFuture);18 return this;19 } 3-13行是檢測AsyncTask的狀態,如果狀態不為PENDING,則會拋異常,這也是為什麼一個AsyncTask只能被執行一次的原因。14行將狀態改為RUNNING,表示該任務正在運行。然後調用AsyncTask的onPreExecute()方法。 由下面代碼可以看出,AsyncTask有三種狀態:PENDING(未運行)、RUNNING(正在運行)、FINISHED(已運行完畢)。
1 public enum Status { 2 /** 3 * Indicates that the task has not been executed yet. 4 */ 5 PENDING, 6 /** 7 * Indicates that the task is running. 8 */ 9 RUNNING,10 /**11 * Indicates that {@link AsyncTask#onPostExecute} has finished.12 */13 FINISHED,14 } FutureTask代碼:
1 public class FutureTask<V> implements RunnableFuture<V> { 2 ...... 3 //構造方法傳入一個Callable對象 4 public FutureTask(Callable<V> callable) { 5 if (callable == null) 6 throw new NullPointerException(); 7 this.callable = callable; 8 this.state = NEW; // ensure visibility of callable 9 }10 public void run() {11 if (state != NEW ||12 !UNSAFE.compareAndSwapObject(this, runnerOffset,13 null, Thread.currentThread()))14 return;15 try {16 Callable<V> c = callable;17 if (c != null && state == NEW) {18 V result;19 boolean ran;20 try {21 result = c.call();//這裡調用了callable.call()方法22 ran = true;23 } catch (Throwable ex) {24 result = null;25 ran = false;26 setException(ex);27 }28 if (ran)29 set(result);30 }31 } finally {32 // runner must be non-null until state is settled to33 // prevent concurrent calls to run()34 runner = null;35 // state must be re-read after nulling runner to prevent36 // leaked interrupts37 int s = state;38 if (s >= INTERRUPTING)39 handlePossibleCancellationInterrupt(s);40 }41 }42 ......43 }
AsyncTask構造方法:
1 public abstract class AsyncTask<Params, Progress, Result> { 2 ...... 3 /** 4 * Creates a new asynchronous task. This constructor must be invoked on the UI thread. 5 */ 6 public AsyncTask() { 7 mWorker = new WorkerRunnable<Params, Result>() { 8 public Result call() throws Exception { 9 mTaskInvoked.set(true);10 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);11 //noinspection unchecked12 return postResult(doInBackground(mParams));13 }14 };15 //建立FutureTask對象的時候傳入了mWorker作為Callable16 mFuture = new FutureTask<Result>(mWorker) {17 @Override18 protected void done() {19 try {20 postResultIfNotInvoked(get());21 } catch (InterruptedException e) {22 android.util.Log.w(LOG_TAG, e);23 } catch (ExecutionException e) {24 throw new RuntimeException("An error occured while executing doInBackground()",25 e.getCause());26 } catch (CancellationException e) {27 postResultIfNotInvoked(null);28 }29 }30 };31 }32 ......33 }
由FutureTask源碼我們可以看出,run()方法裡面調用了c.call(),而AsyncTask 中建立FutureTask的時候傳入了mWorker,所以FutureTask.run()方法裡面c.call()調用的是mWorker對象的call()方法,而AsyncTask裡mWorker重寫了call方法,即上面8-14行,所以c.call()會執行到mWorker.call()方法來。call方法裡面11行將線程的優先順序設定為後台線程,這樣當多個線程並發後很多無關緊要的線程分配的CPU時間將會減少,有利於主線程的處理。 接下來11行執行了doInBackground(mParams)方法,通常我們會重寫該方法來實現商務邏輯操作。然後執行postResult方法,並且將結果返回給FutureTask(因為是FutureTask.run方法調用的此call方法,所以需要返回結果到FutureTask.run方法)。這裡我們先看看postResult:
1 private Result postResult(Result result) {2 @SuppressWarnings("unchecked")3 Message message = sHandler.obtainMessage(MESSAGE_POST_RESULT,4 new AsyncTaskResult<Result>(this, result));5 message.sendToTarget();6 return result;7 }
這裡的sHandler是InternalHandler對象。
1 private static class InternalHandler extends Handler { 2 @SuppressWarnings({"unchecked", "RawUseOfParameterizedType"}) 3 @Override 4 public void handleMessage(Message msg) { 5 AsyncTaskResult result = (AsyncTaskResult) msg.obj; 6 switch (msg.what) { 7 case MESSAGE_POST_RESULT: 8 // There is only one result 9 result.mTask.finish(result.mData[0]);10 break;11 case MESSAGE_POST_PROGRESS:12 result.mTask.onProgressUpdate(result.mData);13 break;14 }15 }16 }
由第9行代碼可知最終會執行AsyncTask的finish方法,代碼如下:
1 private void finish(Result result) {2 if (isCancelled()) {3 onCancelled(result);4 } else {5 onPostExecute(result);6 }7 mStatus = Status.FINISHED;8 }
finish的作用是如果task被取消了就執行onCancelled方法,如果沒有被取消而是正常執行完畢,則執行onPostExecute方法(這也是為什麼task被調用了cancel方法,不會執行onPostExecute的原因)。最後將task的狀態標記為FINISHED。 上面說到mWorker.call會將執行結果返回給FutureTask.run()方法並且繼續往下執行,我們再次看看FutureTask.run方法(20-30行):
1 boolean ran; 2 try { 3 result = c.call(); 4 ran = true; 5 } catch (Throwable ex) { 6 result = null; 7 ran = false; 8 setException(ex); 9 }10 if (ran)11 set(result);
由上面代碼可以看到,執行完c.call後,會執行set(result)方法。
1 protected void set(V v) {2 if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {3 outcome = v;4 UNSAFE.putOrderedInt(this, stateOffset, NORMAL); // final state5 finishCompletion();6 }7 }
最終會執行finishCompletion()方法。
1 private void finishCompletion() { 2 // assert state > COMPLETING; 3 for (WaitNode q; (q = waiters) != null;) { 4 if (UNSAFE.compareAndSwapObject(this, waitersOffset, q, null)) { 5 for (;;) { 6 Thread t = q.thread; 7 if (t != null) { 8 q.thread = null; 9 LockSupport.unpark(t);10 }11 WaitNode next = q.next;12 if (next == null)13 break;14 q.next = null; // unlink to help gc15 q = next;16 }17 break;18 }19 }20 done();21 callable = null; // to reduce footprint22 }
看到21行代碼,會執行FutureTask的done()方法,而這個方法在AsyncTask建構函式中初始化FutureTask對象的時候被重寫了。
1 mFuture = new FutureTask<Result>(mWorker) { 2 @Override 3 protected void done() { 4 try { 5 postResultIfNotInvoked(get()); 6 } catch (InterruptedException e) { 7 android.util.Log.w(LOG_TAG, e); 8 } catch (ExecutionException e) { 9 throw new RuntimeException("An error occured while executing doInBackground()",10 e.getCause());11 } catch (CancellationException e) {12 postResultIfNotInvoked(null);13 }14 }15 }; 這裡主要是驗證postResult是否被調用了,如果沒有被調用著調用postResult函數,因為前面mWorker.call方法裡面調用過了,所以這裡不錯操作。 順便提一下,在AsyncTask的doInBackground方法中如果需要更新UI的話,則調用AsyncTask的publishProgress方法即可:
1 protected final void publishProgress(Progress... values) {2 if (!isCancelled()) {3 sHandler.obtainMessage(MESSAGE_POST_PROGRESS,4 new AsyncTaskResult<Progress>(this, values)).sendToTarget();5 }6 }
publishProgress方法最終也會通過sHandler來調用AsyncTask的onProgressUpdate方法,一般我們如果需要擷取進度的話都需要重寫AsyncTask的onProgressUpdate。 好了,AsyncTask的源碼也分析完了。再次總結一下Asynctask使用的注意事項:
1.非同步任務的執行個體必須在UI線程中建立。
2.execute(Params... params)方法必須在UI線程中調用。
3.不要手動調用onPreExecute(),doInBackground(Params... params),onProgressUpdate(Progress... values),onPostExecute(Result result)這幾個方法。
4.不能在doInBackground(Params... params)中更改UI組件的資訊。
5.一個任務執行個體只能執行一次,如果執行第二次將會拋出異常。