AsyncTask源码分析之一

1, 基本概念

AsyncTask从名字来看,就是异步任务的意思。

首先看看这个类的定义:

public abstract class AsyncTask<Params, Progress, Result> {
•••
}

AsyncTask是一个抽象类,同样,有4个抽象函数,

onPreExecute       //主线程,执行任务之前的一些UI操作
doInBackground    //子线程,执行任务
onProgressUpdate // 任务执行时更新进度信息
onPostExecute    // 主线程,任务完成时更新UI

所以,我们自定义的类必须继承AsyncTask并且实现4个抽象函数,并且主动调用execute方法。

看看AsyncTask的构造函数:

public AsyncTask() {
        mWorker = new WorkerRunnable<Params, Result>() {
            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<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 occurred while executing doInBackground()",
                            e.getCause());
                } catch (CancellationException e) {
                    postResultIfNotInvoked(null);
                }
            }
        };
    }

2, 流程图

从调用execute函数开始,

流程图如下:



3, 任务入队列

详细解析代码:

@MainThread
    public final AsyncTask<Params, Progress, Result> execute(Params... params) {
        return executeOnExecutor(sDefaultExecutor, params);
}
@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;
    }

1, Status是一个枚举类型,它的值标志着任务执行的状态,初始值为PENDING,并且一个任务只能执行一次。

private volatileStatus mStatus = Status.PENDING;

2,由mWorker 和mFuture的初始化可知, mWorker是供mFuture回调的,并且仅有一个call回调函数。mFuture是一个封装的线程类,关键点是这个子线程什么时候执行。

3, 形参exec即是sDefaultExecutor,是AsyncTask内部类SerialExecutor的一个对象。

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

Executor主要做2件事情:

1,调用ArrayDeque的offer方法将子线程(包含任务)入队列。

2,调用ArrayDeque的poll方法对该队列进行出队列操作(先进先出)。

 ArrayDeque的队列elements其实是一个数组: private transient Object[] elements;

3,调用THREAD_POOL_EXECUTOR将该子线程放入线程池。

SerialExecutor类和THREAD_POOL_EXECUTOR对象都是static的,也即是说,无论有多少个AsyncTask子对象,他们都是唯一的,这样才能统一管理各个线程。

4,任务执行

流程图中的第8到16步骤是执行任务, 线程池的原理在此就不论述了。

最后还是会通过mFuture调用mWorker的call函数来执行,只是执行的线程在线程池当中,还是看AsyncTask构造函数中的call函数

mWorker = new WorkerRunnable<Params, Result>() {
            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);
            }
        };

首先调用doInBackground方法执行任务,然后执行完成之后调用postResult方法。

执行完任务之后如何切换到主线程中呢?

通过postResult方法发送消息,利用Handler机制回到主线程中,步骤19到22就是这一过程。

另外,在自写的doInBackground方法的耗时操作时,可以调用publishProgress方法告知主线程任务执行的进度, 

publishProgress最后也会调用postResult方法通过Handler机制切换到主线程并且调用onProgressUpdate方法。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值