Android源码学习-AsyncTask源码浅析

介绍

AsyncTask是一种轻量级的异步任务类,它可以在线程池执行后台任务,然后把执行的进度和结果传递给主线程并在主线程中更新UI。

AsyncTask是一个抽象类,三个泛型分别定义了任务的参数、执行进度以及结果的类型,他们都可以为空,为空时类型指定为Void。由于AsyncTask是抽象,需要继承它并复写5个方法来使用。

public class DownLoadAsyncTask extends AsyncTask {

    private String taskName;

    public DownLoadAsyncTask(String taskName) {
        this.taskName = taskName;
    }

    /**
     * 主线程
     * 做任务开始前准备工作
     */
    @Override
    protected void onPreExecute() {
        super.onPreExecute();
    }

    /**
     * 子线程
     * 执行后台耗时任务
     * @param strings
     * @return
     */
    @Override
    protected String doInBackground(String... strings) {
        try {
            Thread.sleep(3 * 1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return taskName;
    }

    /**
     * 主线程
     * 任务执行进度的回调  
     * 当在doInBackground中调用publishProgress方法时,该方法会被回调
     * @param values
     */
    @Override
    protected void onProgressUpdate(Integer... values) {
        super.onProgressUpdate(values);
    }

    /**
     * 主线程
     * 任务执行结束后回调
     * @param s
     */
    @Override
    protected void onPostExecute(String s) {
        super.onPostExecute(s);
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Log.e("m1ku", s + "finished at " + df.format(new Date()));
    }
}
new DownLoadAsyncTask("task#1").execute("www.baidu.com");

使用AsyncTask时,只需要先实例化并调用其execute方法,以上复写的几个方法机会依次调用完成任务的执行。

源码分析

AsyncTask构造方法

   public AsyncTask() {
      this((Looper) null);
    }
    public AsyncTask(@Nullable Looper callbackLooper) {
        mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper()
            ? getMainHandler()
            : new Handler(callbackLooper);

        mWorker = new WorkerRunnable() {
            public Result call() throws Exception {
                mTaskInvoked.set(true);
                Result result = null;
                try {
                    Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                    //noinspection unchecked
                    result = doInBackground(mParams);
                    Binder.flushPendingCommands();
                } catch (Throwable tr) {
                    mCancelled.set(true);
                    throw tr;
                } finally {
                    postResult(result);
                }
                return result;
            }
        };

        mFuture = new FutureTask(mWorker) {
            @Override
            protected void done() {
                try {
                    postResultIfNotInvoked(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);
                }
            }
        };
    }

首先获取到主线程的Handler对象,然后初始化一个WorkerRunnable对象mWorker,该对象实现了Callable接口,mParams参数是这个对象的成员变量。使用mWorker构造了FutureTask对象mFuture,FutureTask实现了RunnableFuture接口,RunnableFuture又继承了Runnable和Future接口,所以FutureTask是一个可取消的并且可以被线程池执行的异步任务计算类。

execute方法

@MainThread
public final AsyncTask execute(Params... params) {
    return executeOnExecutor(sDefaultExecutor, params);
}

@MainThread
    public final AsyncTask 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;
    }

首先判断当前不在等待状态,如果状态是RUNNING正在运行时抛出异常,如果状态是FINISHED已经结束时也抛出异常即一个AsyncTask只能执行一次。将当前task状态置为RUNNING,并调用onPreExecute方法,将传入的参数赋值给前面初始化过的mWorker对象,最后调用sDefaultExecutor的execute方法传入mFuture。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);
        }
    }
}

在execute方法中,将Runnable对象添加到mTasks队列中,并在该Runnable的run方法中调用了mFuture的run。

由于当前mActive为空,调用scheduleNext方法,该方法中首先为mActive赋值,如果不为空则使用THREAD_POOL_EXECUTOR线程池执行mActive。mActive为mTasks的第一个元素,它的run方法被调用,mFuture的run方法被调用,执行完毕后再finally中又调用了scheduleNext方法继续执行下一个Runnable即执行mFuture任务对象。mFuture的run方法如下

public void run() {
    if (state != NEW ||
        !U.compareAndSwapObject(this, RUNNER, null, Thread.currentThread()))
        return;
    try {
        Callable c = callable;
        if (c != null && state == NEW) {
            V result;
            boolean ran;
            try {
                result = c.call();
                ran = true;
            } catch (Throwable ex) {
                result = null;
                ran = false;
                setException(ex);
            }
            if (ran)
                set(result);
        }
    } finally {
        // runner must be non-null until state is settled to
        // prevent concurrent calls to run()
        runner = null;
        // state must be re-read after nulling runner to prevent
        // leaked interrupts
        int s = state;
        if (s >= INTERRUPTING)
            handlePossibleCancellationInterrupt(s);
    }
}

其中调用了c.call()方法,即传入的Callable对象mWorker的call方法

public Result call() throws Exception {
    mTaskInvoked.set(true);
    Result result = null;
    try {
        Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
        //noinspection unchecked
        result = doInBackground(mParams);
        Binder.flushPendingCommands();
    } catch (Throwable tr) {
        mCancelled.set(true);
        throw tr;
    } finally {
        postResult(result);
    }
    return result;
}

调用doInBackground方法,而在doInBackground中我们会手动调用publishProgress方法

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

使用Handler发送进度更新消息,将当前线程从线程池中切换到了主线程中

private static class InternalHandler extends Handler {
    public InternalHandler(Looper looper) {
        super(looper);
    }

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

在handleMessage中调用了onProgressUpdate方法对外公布了任务执行的进度。最后在finally块中调用了postResult方法

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

这里同样是将结果通过handler发送到了主线程中,如上在handleMessage中调用finish方法

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

判断当前任务已经取消时回调取消方法,否则回调onPostExecute方法对外公布任务执行的结果,最后将任务状态置为FINISHED。

通过分析AsyncTask的源码,可以得出几点结论

  • 一个AsyncTask只能执行一次。
  • 由于sHandler是一个静态成员在类加载时进行初始化,所以AsyncTask必须要在主线程中加载。
  • AsyncTask中有两个线程池,SERIAL_EXECUTOR负责任务的排队,THREAD_POOL_EXECUTOR才负责任务的执行。
  • AsyncTask中任务默认是串行执行的。

你可能感兴趣的:(Android源码学习-AsyncTask源码浅析)