Android基于源码分析AsyncTask的工作流程

原创 2015年11月18日 15:14:06


AsyncTask简介

    AsyncTask是一种轻量级的异步任务类,它实质上也是对handler和thread做了封装,使用线程池执行后台任务,是一个比较好用的异步类。

AsyncTask的3个参数和4个步骤

  3个参数:

        params:我们传递给异步任务执行的参数类型;

        progress:异步任务在执行的时候,会将执行的进度返回给UI的参数类型;

        Result:异步任务执行结束后返回的数据参数类型。

  4个步骤:

        onPreExecute():这个方法是在执行异步任务之前执行的,通常用来做一些控件的初始化工作,此方法在UI线程中执行。

        doInBackground(Params…) :在onPreExecute()方法后执行,这个方法就是在工作线程中执行的,可以做一些相对耗时的任务,在执行的时候,如果调用        publishProgress(Progress... values)方法,可以更新任务的进度,执行结束后,将执行的结果返回给onPostExecute(Result result)处理。

        onProgressUpdate(Progress... values):该方法在UI线程中执行,如在异步任务执行时(doInBackground()里面)调用publishProgress()方法,这个方法可以得到返回的进度参数,然后在控件上更新进度条。

        onPostExecute(Result result):当异步操作任务执行完成后会将结果返回到这个方法,我们可以将返回的结果显示在控件上,这个方法这是在UI线程上执行的。

AsyncTask的源码分析

    上面说了那么多,都是一些很理论的东西,只知道有这么回事儿,但是究竟为什么要这么执行呢?不急,我们从源码的角度来看看吧!

    我们知道,要使用AsyncTask,必须先自己定义一个类继承它(假如是MyAsyncTask),然后在主线程中创建这个类,使用MyAsyncTask().execute(params...)来执行,好了基础的代码这里就不贴,重点在源码分析嘛!(注意我这里是基于Android4.4的源码),当我们点到execute这个方法,跳到系统源码类中的:

public final AsyncTask<Params, Progress, Result> execute(Params... params) {
        return executeOnExecutor(sDefaultExecutor, params);
    }

这个方法没什么,只有一个参数sDefaultExecutor,这个参数是啥:

    public static final Executor SERIAL_EXECUTOR = new SerialExecutor();

    private static final int MESSAGE_POST_RESULT = 0x1;
    private static final int MESSAGE_POST_PROGRESS = 0x2;

    private static final InternalHandler sHandler = new InternalHandler();

    private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
    private final WorkerRunnable<Params, Result> mWorker;
    private final FutureTask<Result> mFuture;

    private volatile Status mStatus = Status.PENDING;
    
    private final AtomicBoolean mCancelled = new AtomicBoolean();
    private final AtomicBoolean mTaskInvoked = new AtomicBoolean();

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

sDefaultExecutor实际上就是一个扩展了Executor的SerialExecutor内部类,这里sDefaultExecutor实际上就是一个串行的线程池,也就是说AsyncTask所有的任务在这个线程池中排队执行。这个方法里面,我们主要先看形参Runnable,在try{}语句中有个r.run(),凭直觉,这里应该就是开启线程干活了。这儿先留个伏笔,我们接着往下看:

    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(),从这也说明了它是在执行异步操作之前先执行的,我们可以看到:onPreExecute()、doInBackground(Params... params)、onProgressUpdate(Progress... values)、onPostExecute(Result result)这几个方法都是protected修饰的,同时public abstract class AsyncTask<Params, Progress, Result>是一个抽象类,所以我们一般是自己写一个类继承AsyncTask,然后子类里面实现这些方法来使用。接着看,这里有2个很重要的成员变量参数,mWorker和mFuture,在看到exec.execute(mFuture)这一行代码的时候,对应前面说的伏笔,那么mFuture这个就是我们要的Runnable对象,r.run(),也就是mFuture干活了。那么这2个这么重要成员变量哪来的呢?接着看:

    /**
     * Creates a new asynchronous task. This constructor must be invoked on the UI thread.
     */
    public AsyncTask() {
        mWorker = new WorkerRunnable<Params, Result>() {
            public Result call() throws Exception {
                mTaskInvoked.set(true);

                Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                //noinspection unchecked
                return postResult(doInBackground(mParams));
            }
        };

        mFuture = new FutureTask<Result>(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 occured while executing doInBackground()",
                            e.getCause());
                } catch (CancellationException e) {
                    postResultIfNotInvoked(null);
                }
            }
        };
    }

这个AsyncTask()实际上是构造函数,在我们创建自己的AsyncTask(MyAsyncTask)的时候,这个类就在UI线程中被调用了。先看看mWorker,这里直接创建了WorkerRunnable<Params, Result>()这个静态抽象的内部类对象,我们看看这是个啥:

    private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> {
        Params[] mParams;
    }
public interface Callable<V> {
    /**
     * Computes a result, or throws an exception if unable to do so.
     *
     * @return computed result
     * @throws Exception if unable to compute a result
     */
    V call() throws Exception;
}

看到最后,发现mWorker是实现了Callable接口的类,这个call()方法,在上面创建的时候实现。再看看mFuture是啥,这里要点到FutureTask类看:

    /**
     * Creates a {@code FutureTask} that will, upon running, execute the
     * given {@code Callable}.
     *
     * @param  callable the callable task
     * @throws NullPointerException if the callable is null
     */
    public FutureTask(Callable<V> callable) {
        if (callable == null)
            throw new NullPointerException();
        this.callable = callable;
        this.state = NEW;       // ensure visibility of callable
    }

前面mFuture = new FutureTask<Result>(mWorker)这行代码中,就直接把mWorker传到了FutureTask的成员变量this.callable = callable中的this.callable中。好,看看FutureTask是什么东东:

public class FutureTask<V> implements RunnableFuture<V>
/**
 * A {@link Future} that is {@link Runnable}. Successful execution of
 * the {@code run} method causes completion of the {@code Future}
 * and allows access to its results.
 * @see FutureTask
 * @see Executor
 * @since 1.6
 * @author Doug Lea
 * @param <V> The result type returned by this Future's {@code get} method
 */
public interface RunnableFuture<V> extends Runnable, Future<V> {
    /**
     * Sets this Future to the result of its computation
     * unless it has been cancelled.
     */
    void run();
}

终于看清楚啦,这个mFuture就是咱们需要的Runnable!干活的确定是mFuture了。好我们回过头看看executeOnExecutor方法中的:
exec.execute(mFuture);

这个exec就是传进来的sDefaultExecutor,而sDefaultExecutor我们上面看了,实际就是SerialExecutor类,看看类里面的:

 public synchronized void execute(final Runnable r) {
            mTasks.offer(new Runnable() {
                public void run() {
                    try {
                        r.run();
                    } finally {
                        scheduleNext();
                    }
                }
            });
            if (mActive == null) {
                scheduleNext();
            }
        }

第5行r.run();到这里,也就是说执行mFuture.run()了,我们再次看看FutureTask中的run():

    public void run() {
        if (state != NEW ||
            !UNSAFE.compareAndSwapObject(this, runnerOffset,
                                         null, Thread.currentThread()))
            return;
        try {
            Callable<V> 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);
        }
    }

挑重点看,这个方法里把之前创建FutureTask的时候mFuture = new FutureTask<Result>(mWorker)中的mWorker付给Callable<V> c,然后执行result = c.call(),也就是说

mWorker = new WorkerRunnable<Params, Result>() {
            public Result call() throws Exception {
                mTaskInvoked.set(true);

                Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                //noinspection unchecked
                return postResult(doInBackground(mParams));
            }
        };

这个call()方法执行了。仔细看看这个方法里面,return postResult(doInBackground(mParams));终于看到了doInBackgroud了,原来,doInBackground永远执行在Runnable中,也就是说在工作线程中执行,所以我们可以再这里面做一些稍微耗时的工作。当doInBackground返回结果了,我们接着看postResult(doInBackground(mParams)):

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

是不是一种似曾相识的感觉油然而生,这里居然就是使用的handler发送的消息啊!我们看看这个内部类sHandler:

private static final InternalHandler sHandler = new InternalHandler();
    private static class InternalHandler extends Handler {
        @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;
            }
        }
    }

不难看出InternalHandler实际上就是一个Handler,刚才postResult在发送消息时,带的一个参数MESSAGE_POST_RESULT就在这个InternalHandler里的handleMessage方法中处理了。我们接着看

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

finish这个方法很简单,逻辑也很清晰,如果AsyncTask被取消执行了,那么就回调onCancelled(result),否者继续执行onPostExecute(result),这里我们可以了解到需要停止AsyncTask可以在onCancelled(result)这里做处理了。可以看出,doInBackground的返回结果会传递给onPostExecute方法执行,到这里,整个AsycnTask的工作原理就分析完了,不得不佩服老外写程序的思想,简洁的封装了handler和Thread后,就有了这么一个轻量异步处理任务类!























版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

【openstack】openstack网络详解(Essex版)

openstack网络详解 本博客欢迎转发,但请保留原作者(孔令贤HW)信息!内容系本人学习、研究和总结,如有雷同,实属荣幸! 这篇文章基本是参考了http://www.mirantis.com/b...

Git使用笔记

声明: 本博客欢迎转发,但请保留原作者信息! 新浪微博:@孔令贤HW; 博客地址:http://blog.csdn.net/lynn_kong 内容系本人学习、研究和总结,如有雷同,实属荣幸! ...

【OpenStack】学习OpenStack的历程--送给初学者

近期有很多人通过微博、qq或者我的博客向我咨询OpenStack相关的问题,其实对于别人的求助,我是乐于解答的,毕竟表示大家看得起我。但有的人的问题我听了之后,心里却想要不要回答他,因为他的问题真的很...

其实我有些迷茫

中午吃完饭,刷完碗,又坐到了电脑前。媳妇最讨厌的就是我一回家就开电脑,她总说:在公司看电脑,回家还看,歇一歇吧,眼睛会出事儿的。我不知道该怎么反驳,我的工作离不开电脑,离不开网络。网络在我眼里,就是一...

近况(2013-12-16)

因为工作内容的原因,现在写一篇博客越来越费劲。 很多零碎的时间挤在一起,在效率上很难等同于一大块时间的利用。 团队内部有很多事情需要协调,团队之外有更多的事情需要支撑,需要推动,需要拉通,每天疲于...

近期总结(2013/7/14)

近期总结(2013/7/14) 一段时间过后总要总结一下,不能一味往前冲,而迷失了目标和方向,以及前进的动力。 前段时间可以说是我职业生涯的一次重大转折,经过两年的努力,由一个开发人员,被提拔为一个...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)