AsyncTask源碼分析,asynctask源碼

來源:互聯網
上載者:User

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.一個任務執行個體只能執行一次,如果執行第二次將會拋出異常。

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.