AsyncTask 源码阅读

Table of Contents

AsyncTask是Android提供的一个封装类, 可以实现后台线程与UI线程的交互.
本文是该类的源码的阅读笔记, 至于AsyncTask的用法, 可以去查阅相关的资料.

AsyncTask的源码实现主要是封装了 HandlerThread 两个功能. 下面是详细的代码实现. 该类是一个抽象类.

thread相关

AsyncTask的源码中定义了如下与"thread"相关的变量或函数.

sThreadFactory

该变量是一个实现了ThreadFacotry类的匿名类变量, 主要实现了 newThread()函数, 该函数定义了创建线程的方法. 创建的线程 接受一个Runnable对象. 这个线程就是doInBackground()函数 所执行的线程.

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());
    }
};

sPoolWorkQueue

创建了一个"阻塞队列". 用于存放Runnable对象.

THREAD_POOL_EXECUTOR

该变量是一个ThreadPoolExecutor对象, 基于上面创建的两个 变量 "sThreadFacotry" 和 "sPoolWorkQueue" 创建, 意思即 这个executor执行的thread会从sThreadFactory中创建, 并且 提交给这个executor的runnable对象在执行前, 都会存放到 sPoolWorkQueue中.

public static final Executor THREAD_POOL_EXECUTOR
         = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,
                 TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);

SERIAL_EXECUTOR

该变量是一个SerialExecutor对象, 后者是一个自定义的 Executor子类, 该类实现了"顺序"执行任务的功能, 即同一时刻 只能提交并执行一个runnable. 该对象是AsyncTask默认的执行 executor.

该类通过THREAD_POOL_EXECUTOR 来执行实际的"线程"功能.见代码:

private static class SerialExecutor implements Executor {
     final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
     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);
         }
     }
 }

sWorker和mFuture

这两个变量是在AsyncTask的构造函数中创建的.

mWorker是一个Callable类, 它的call()函数主要就是执行 doInBackground() 这个函数, 然后将结果通过handler传递给UI线程.

mFuture是一个FutureTask变量.它封装了mWorker, 这样可以支持任务的取消.

handler相关

AsyncTask内部定义了一个私有类 InternalHandler, 该类使用了 UI线程的looper. 所以该Handler对Message的处理都是在UI线程中进行的.

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]);
                break;
            case MESSAGE_POST_PROGRESS:
                result.mTask.onProgressUpdate(result.mData);
                break;
        }
    }
}

流程

execute()函数过程

使用AsyncTask时, 一般通过调用 execute(var) 函数执行任务, 该函数 调用了executeOnExecutor()函数, 默认使用 sDefaultEExecutor即 SERIAL_EXECUTOR来执行任务. 下面是后者的实现:

@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;
}

该函数首先判断任务状态. 然后调用 onPreExecute(), 这是在UI线程调用的. 然后是调用exec.execute(mFuture). 从前面的内容可以知道, 这行代码就会 在线程中调用doInBackground()函数. 等doInBackground执行完成后, 会调用postResult() 提交结果. postResult()通过handler将结果传递给UI线程执行.

private Result postResult(Result result) {
    @SuppressWarnings("unchecked")
    Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
            new AsyncTaskResult<Result>(this, result));
    message.sendToTarget();
    return result;
}

前面handler的内容可知, handler最后会调用到finish()函数, 该函数会调用到 onPostExecute().

private void finish(Result result) {
    if (isCancelled()) {
        onCancelled(result);
    } else {
        onPostExecute(result);
    }
    mStatus = Status.FINISHED;
}

发布进度

可以通过publishProgress函数发布当前进度.该函数会通过handler向UI线程推送消息.

@WorkerThread
protected final void publishProgress(Progress... values) {
    if (!isCancelled()) {
        getHandler().obtainMessage(MESSAGE_POST_PROGRESS,
                new AsyncTaskResult<Progress>(this, values)).sendToTarget();
    }
}

该消息的处理会调用到onProgressUpdate()函数.

Created At <2015-02-20 Fri 23:25> by Luis Xu. Email: xuzhengchaojob@gmail.com