Android `AsyncTask`簡要分析

Android `AsyncTask`簡要分析

AsyncTask簡要分析

經典異步任務:AsyncTask,使用場景有:批量下載,批量拷貝等。官方文檔就直接給出了一個批量下載的示例。

    private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
       protected Long doInBackground(URL... urls) {
           int count = urls.length;
           long totalSize = 0;
           for (int i = 0; i < count; i++) {
               totalSize += Downloader.downloadFile(urls[i]);
               publishProgress((int) ((i / (float) count) * 100));
               // Escape early if cancel() is called
               if (isCancelled()) break;
           }
           return totalSize;
       }
  
       protected void onProgressUpdate(Integer... progress) {
           setProgressPercent(progress[0]);
       }
  
       protected void onPostExecute(Long result) {
           showDialog("Downloaded " + result + " bytes");
       }
   }

    // Once created, a task is executed very simply:
    new DownloadFilesTask().execute(url1, url2, url3);

這裏簡單看一下,AsyncTask中的幾個經典問題:

  1. AsyncTask開了幾個線程?
  2. AsyncTask怎麼實現的線程調度?

好吧,就想到了這兩個問題。第一個問題,明顯是坑。答案是未知的。看手機 cpu個數了。

private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
// We want at least 2 threads and at most 4 threads in the core pool,
// preferring to have 1 less than the CPU count to avoid saturating
// the CPU with background work
private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4));
private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;

然後是第二個問題。簡單回答就是一句話,通過開啓線程執行具體邏輯,然後通過handler將結果發送到主線程。

進一步追蹤的話,就會發現,AsyncTask = ThreadPoolExecutor + Handler 。

通過源碼可以看到,AsyncTask在構造方法裏面,已經完成了全部的準備工作。

  • MainHandler已經創建。
  • FutureTask已經準備了。(說實話,FutureTask難過的讓人吐血)

         public AsyncTask(@Nullable Looper callbackLooper) {
         mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper()
             ? getMainHandler()
             : new Handler(callbackLooper);
    
         mWorker = new WorkerRunnable<Params, Result>() {
             public Result call() throws Exception {
                 mTaskInvoked.set(true);
                 Result result = null;
                 try {
                     Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                     //noinspection unchecked
                     result = doInBackground(mParams);  // mParams 核心邏輯
                     Binder.flushPendingCommands();
                 } catch (Throwable tr) {
                     mCancelled.set(true);
                     throw tr;
                 } finally {
                     postResult(result);  // 核心邏輯
                 }
                 return result;
             }
         };
    
         mFuture = new FutureTask<Result>(mWorker) {
             @Override
             protected void done() {
                 try {
                     postResultIfNotInvoked(get());  // 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);
                 }
             }
         };
     }
  • 系消息

      @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;
      }
    
      // 核心邏輯:handler,將結果發送到主線程
      private Result postResult(Result result) {
          @SuppressWarnings("unchecked")
          Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
                  new AsyncTaskResult<Result>(this, result));
          message.sendToTarget();
          return result;
      }
    原文地址https://www.cnblogs.com/pythoncat/p/10514933.html
    
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章