Android:AsyncTask源碼解讀

qinli0606 9年前發布 | 6K 次閱讀 AsyncTask Android開發 移動開發

標題黨

AsyncTask源碼解讀,解讀這么流弊的標題,嚇得我都不敢寫下去啦!菜鳥一枚,寫不對的地方,請各位大神在留下評論或拍磚,我會為大家貢獻更多多的妹子圖。

PS妹子圖鎮樓,可以增加閱讀量

AsyncTask簡單使用

  1. 直接上代碼,很簡單就是在子線程中結算1到100的和。妹子你走開,我要開始擼代碼啦!

    public static void main(String arg[]) throws InterruptedException {
         MyTask task = new MyTask();
         task.execute(100);
     }
    static class MyTask extends AsyncTask<Integer, Integer, Integer> {
         @Override
         protected void onPreExecute() {
             System.out.println("onPreExecute");
             super.onPreExecute();
         }
         @Override
         protected void onProgressUpdate(Integer... values) {
             System.out.println("onProgressUpdate " + values[0]);
             super.onProgressUpdate(values);
         }
         @Override
         protected Integer doInBackground(Integer... integers) {
             //在新的線程中執行
             int sum = 0;
             for (int i = 0; i < integers[0]; i++) {
                 sum = sum + i;
                 publishProgress(i);//給InternalHandler發送進度更新的消息
             }
             return sum;
         }

     @Override
     protected void onPostExecute(Integer integer) {
         //將子線程的結果post到主線程
         super.onPostExecute(integer);
     }
    

    }</code></pre> </li>

  2. 稍微介紹重要的幾個方法;暫時忘記到妹子圖吧!看看以下四個方法:@MainThread表示在主線程中執行,而@WorkerThread表示在子線程中執行

    @MainThread
    protected void onPreExecute() 
    @MainThread
    protected void onPostExecute(Result result) 
    @MainThread
    protected void onProgressUpdate(Progress... values)
    @WorkerThread
    protected abstract Result doInBackground(Params... params)
    • onPreExecute:表示該方法是運行在主線程中的。在AsyncTask執行了execute()方法后就會在UI線程上執行onPreExecute()方法,該方法在task真正執行前運行,我們通常可以在該方法中顯示一個進度條,從而告知用戶后臺任務即將開始。

    • doInBackground :表示該方法是運行在單獨的工作線程中的,而不是運行在主線程中。doInBackground會在onPreExecute()方法執行完成后立即執行,該方法用于在工作線程中執行耗時任務,我們可以在該方法中編寫我們需要在后臺線程中運行的邏輯代碼,由于是運行在工作線程中,所以該方法不會阻塞UI線程。該方法接收Params泛型參數,參數params是Params類型的不定長數組,該方法的返回值是Result泛型,由于doInBackgroud是抽象方法,我們在使用AsyncTask時必須重寫該方法。在doInBackground中執行的任務可能要分解為好多步驟,每完成一步我們就可以通過調用AsyncTask的publishProgress(Progress…)將階段性的處理結果發布出去,階段性處理結果是Progress泛型類型。當調用了publishProgress方法后,處理結果會被傳遞到UI線程中,并在UI線程中回調onProgressUpdate方法,下面會詳細介紹。根據我們的具體需要,我們可以在doInBackground中不調用publishProgress方法,當然也可以在該方法中多次調用publishProgress方法。doInBackgroud方法的返回值表示后臺線程完成任務之后的結果。

    • onProgressUpdate 上面我們知道,當我們在doInBackground中調用publishProgress(Progress…)方法后,就會在UI線程上回調onProgressUpdate方法

      注解,表示該方法是在主線程上被調用的,且傳入的參數是Progress泛型定義的不定長數組。如果在doInBackground中多次調用了publishProgress方法,那么主線程就會多次回調onProgressUpdate方法。

    • onPostExecute :表示該方法是在主線程中被調用的。當doInBackgroud方法執行完畢后,就表示任務完成了,doInBackgroud方法的返回值就會作為參數在主線程中傳入到onPostExecute方法中,這樣就可以在主線程中根據任務的執行結果更新UI。

    • </ul> </li> </ol>

      內部實現

      上面講了那么多,然而都不是重點,現在才剛開始進入主題。AsyncTask其實就是用線程池和和handle實現的!

      1. AsyncTask的三個狀態

        public enum Status {
             /**

          * Indicates that the task has not been executed yet.
          * 還沒有執行
          */
         PENDING,
         /**
          * Indicates that the task is running.
         *  正在執行
         */
         RUNNING,
         /**
          * Indicates that {@link AsyncTask#onPostExecute} has finished.
          * 執行結束
          */
         FINISHED,
        

        }</code></pre> </li>

      2. 子線程與主線程通訊:(handle)

        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]);//調用onPostExecute 將結果post到主線程
                     break;
                 case MESSAGE_POST_PROGRESS://調用onProgressUpdate更新進度 
                     result.mTask.onProgressUpdate(result.mData);
                     break;
             }
         }
        

        } private void finish(Result result) { if (isCancelled()) { onCancelled(result); } else { onPostExecute(result); } mStatus = Status.FINISHED; }</code></pre> </li>

      3. 構造函數

        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);//調用doInBackground 在子線程中做一系列的事情
                     Binder.flushPendingCommands();
                     return postResult(result);//給InternalHandler發送一個doInBackground任務執行完成的消息
                 }
             };

         mFuture = new FutureTask<Result>(mWorker) {
             @Override
             protected void done() {
                 try {
                     postResultIfNotInvoked(get());//等待mWorker的call方法執行完成
                 } 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);//如果doInBackground發生異常,則向主線程發送一個null的結果
                 }
             }
         };
        

        }</code></pre> </li>

      4. execute(params)最終調用executeOnExecutor

        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();//在主線程總調用onPreExecute
             mWorker.mParams = params;//mWorker 設置參數
             exec.execute(mFuture);//線程池執行futureTask
             return this;
         }
      5. AsyncTask執行一個task的流程圖
      6. </ol>

        流程圖1

        流程圖2

        流程圖3

        流程圖4

         

        來自:http://www.jianshu.com/p/589358898780

         

 本文由用戶 qinli0606 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!