AsyncTask 源码阅读

基于 Android-24

AsyncTask 是安卓 sdk 提供的一个异步框架,用来解决耗时任务线程和主线程之间通讯问题。

但是因为 sdk 升级过程中的几次重大改动,导致 AsyncTask 有了很多『坑』

AsyncTask 源码阅读_第1张图片
asyncTask_01.png

但是不可否认 AsyncTask 框架的设计,还有值得学习的。

AsyncTask 框架

AsyncTask 核心代码只有一个文件,其中包含

 3 个静态内部类
 1 个静态内部抽象类
 1 个枚举类
 1 个 AsyncTask 类
AsyncTask 源码阅读_第2张图片
asyncTask_03.png

使用方法

    new AsyncTask(){

        @Override
        protected Object doInBackground(Object[] params) {
            return null;
        }

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
        }

        @Override
        protected void onPostExecute(Object o) {
            super.onPostExecute(o);
        }
    }.execute();

三个泛型参数分别代表:传入参数类型、任务进度单位、返回结果类型

AsyncTask 线程池管理

public static final Executor THREAD_POOL_EXECUTOR;

static {
    ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
            CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS,
            sPoolWorkQueue, sThreadFactory);
    threadPoolExecutor.allowCoreThreadTimeOut(true);
    THREAD_POOL_EXECUTOR = threadPoolExecutor;
}

其中:

private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();

// 核心线程数最小为2 ,最大为 4 。根据 cpu 核数确定。
private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4));
// 最大线程数量为 cpu 核数的 2 倍 - 1
private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
// 非核心线程数存活时间为 30s 
private static final int KEEP_ALIVE_SECONDS = 30;

AsyncTask 创建的线程,都会用 『AsyncTask #』开头标记

private static final ThreadFactory sThreadFactory = new ThreadFactory() {
    private final AtomicInteger mCount = new AtomicInteger(1);

    public Thread newThread(Runnable r) {
        return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());
    }
};

AsyncTask 的任务队列长度为 128

private static final BlockingQueue sPoolWorkQueue =
        new LinkedBlockingQueue(128);

关于线程池参数含义参考Java 线程池源码阅读笔记

AsyncTask 任务执行过程

  1. execute 方法

     AsyncTask 有三个 execute 方法。
     
     1.直接通过内置线程调度器,执行一个 runnable
         public static void execute(Runnable runnable)
         
     2.使用内置线程调度器,传入参数执行 doInBackground 中的任务。    
         public final AsyncTask execute(Params... params)
     
     3.使用自定义任务调度器,传入参数执行 doInBackground 中的任务。    
     public final AsyncTask executeOnExecutor(Executor exec,
         Params... params)
         
     其中『第二种』方法,会调用『第三种』方法,不过是将内置的线程调度器传递过去
    
  2. sDefaultExecutor 成员变量

    sDefaultExecutor 是一个线性调度器

    private static class SerialExecutor implements Executor {
     final ArrayDeque mTasks = new ArrayDeque();
     Runnable mActive;
    
     public synchronized void execute(final Runnable r) {
         mTasks.offer(new Runnable() {
             public void run() {
                 try {
                     r.run();
                 } finally {
                     scheduleNext();
                 }
             }
         });
         if (mActive == null) {
             scheduleNext();
         }
     }
    
     protected synchronized void scheduleNext() {
         if ((mActive = mTasks.poll()) != null) {
             THREAD_POOL_EXECUTOR.execute(mActive);
         }
     }
    

    }

SerialExecutor 类有以下几个特点

1. execute 和 scheduleNext 方法都持有一个对像锁。
2. 如果队列 mTasks 不为空,mActive 则不为空。
3. mActive 为空,则表示队列已空,执行 scheduleNext 执行队列刚添加的任务。
4. mActive 不为空,添加任务到队列尾部。等待任务出栈。

流程图大致如下

AsyncTask 源码阅读_第3张图片
asyncTask_02.png
  1. executeOnExecutor() 方法

     public final AsyncTask executeOnExecutor(Executor exec,
         Params... params) {
     if (mStatus != Status.PENDING) {
     ……
     }
    
     mStatus = Status.RUNNING;
    
     onPreExecute();
    
     mWorker.mParams = params;
     exec.execute(mFuture);
    
     return this;
     }
    

    executeOnExecutor 方法中执行了 onPreExecute() ,然后执行 exec.execute(mFuture)。
    其中 mFuture 代码如下

     public AsyncTask() {
     mWorker = new WorkerRunnable() {
         public Result call() throws Exception {
             mTaskInvoked.set(true);
    
             Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
             //noinspection unchecked
             Result result = doInBackground(mParams);
             Binder.flushPendingCommands();
             return postResult(result);
         }
     };
    
     mFuture = new FutureTask(mWorker) {
         @Override
         protected void done() {
             try {
                 postResultIfNotInvoked(get());
             } ……
         }
     };
     }
    

    通过以上代码,可以得出

      1. AsyncTask 任务封装到 FutureTask 中。
      2. 在执行任务之前先执行 onPreExecute(),此时依旧在主线程。
      3. doInBackground() 在线程成中执行。
      4. 任务执行完毕会执行 postResult 或者 postResultIfNotInvoked 发送消息给主线程
    
  2. 返回结果

     private void postResultIfNotInvoked(Result result) {
         final boolean wasTaskInvoked = mTaskInvoked.get();
         if (!wasTaskInvoked) {
             postResult(result);
         }
     }
    
     private Result postResult(Result result) {
         @SuppressWarnings("unchecked")
         Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
                 new AsyncTaskResult(this, result));
         message.sendToTarget();
         return result;
     }
    

    通过 postResult 方法返回结果给主线程。

      private static Handler getHandler() {
         synchronized (AsyncTask.class) {
             if (sHandler == null) {
                 sHandler = new InternalHandler();
             }
             return sHandler;
         }
     }
     
         private static class InternalHandler extends Handler {
     public InternalHandler() {
         super(Looper.getMainLooper());
     }
    
     @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]);
                 break;
             case MESSAGE_POST_PROGRESS:
                 result.mTask.onProgressUpdate(result.mData);
                 break;
         }
     }
    

最终会调用 finish 方法

    private void finish(Result result) {
        if (isCancelled()) {
            onCancelled(result);
        } else {
            onPostExecute(result);
        }
        mStatus = Status.FINISHED;
    }
  1. 总结 AsyncTask 框架的时序图如下
AsyncTask 源码阅读_第4张图片
asyncTask_04.png

你可能感兴趣的:(AsyncTask 源码阅读)