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



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后,就有了这么一个轻量异步处理任务类!























  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值