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;
      }
03-12 18:46