AsyncTask工作原理分析

标签(空格分隔): android 源码分析 no


  • AsyncTask工作原理分析
    • AsyncTask基本介绍
    • AsyncTask的工作原理

AsyncTask基本介绍


AsyncTask是Android提供的一种轻量级异步任务类,它可以使用线程池执行后台任务。其使用Handler作为子线程与主线程交互的桥梁。

从图中我们可以看出AsyncTask中方法的执行方向。

AsyncTask的工作原理

这里我们先从executeOnExecutor()方法着手

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

从第一行的注解可以看出该方法必须执行在主线程当中,并且从第五行的switch-case和第十六行的设置标志位可以看出该方法只能被执行一次。并且在正式执行前调用了第十八行的onPreExecute()方法。所以我们可以在重写该方法时执行要一些准备工作。最后的重点是第二十一行,这里使用我们传入的线程池执行后台计算。

我们查看一下第二十行的mWorker是如何工作的:

    private final WorkerRunnable mWorker;    ...    private static abstract class WorkerRunnable implements Callable {        Params[] mParams;    }    ...    public interface Callable {        V call() throws Exception;    }    ...    mWorker = new WorkerRunnable() {            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);            }        };    ...    private Result postResult(Result result) {        @SuppressWarnings("unchecked")        Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,                new AsyncTaskResult(this, result));        message.sendToTarget();        return result;    }

通过第十八行和第二十行可以看出当mWorker的Call方法被调用时执行了doInBackground方法,并且将放回结果提交给了postResult方法。postResult方法将消息传递给了Handler:

    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:                    result.mTask.finish(result.mData[0]);                    break;                case MESSAGE_POST_PROGRESS:                    result.mTask.onProgressUpdate(result.mData);                    break;            }        }    }    ...    private void finish(Result result) {        if (isCancelled()) {            onCancelled(result);        } else {            onPostExecute(result);        }        mStatus = Status.FINISHED;    }

这里的Handler的操作也解释了为什么onCancelled和onPostExecute是互斥的。

接下来我们查看一下直接使用execute()方法时内部发生的事情

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

可以看出该方法还是执行了executeOnExecutor方法,可是我们并没有传入线程池,这里使用的线程池是什么东西呢?

    public static final Executor SERIAL_EXECUTOR = new SerialExecutor();    ...    private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;    ...    public static final Executor THREAD_POOL_EXECUTOR            = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,                    TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);    ...    private static class SerialExecutor implements Executor {        final ArrayDeque mTasks = new ArrayDeque();        Runnable mActive;        public synchronized void execute(final Runnable r) {            mTasks.offer(() -> {                    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对象放入任务队列当中,此时并没有去立即执行。接下来当当前没有正在活动的对象时,调用调度方法去从任务列表中取出一个任务交由THREAD_POOL_EXECUTOR线程池中去执行,并且由于execute将scheduleNext方法包装进了任务方法,这就导致只要任务列表还有任务就能不断的串行执行。由此可以看出,sDefaultExecutor的工作并不是执行任务,而是调度任务。真正的任务执行是交给了THREAD_POOL_EXECUTOR去执行。

更多相关文章

  1. SpringBoot 2.0 中 HikariCP 数据库连接池原理解析
  2. android studio 导入Google源码
  3. Android的DDMS中的Threads的各个字段的含义
  4. Android中实现Runnable接口简单例子
  5. Android(安卓)ListView中动态显示和隐藏Header&Footer的方法
  6. Android系列之Intent传递对象的几种实例方法
  7. Android引入第三方jar包的方法
  8. [android] Proguard代码混淆器如何排除指定的类或子类
  9. Android——ContentProvider总结

随机推荐

  1. 30个高质量并且免费的Android图标【Andro
  2. 《android framework常用api源码分析》之
  3. Android 中的注解详细介绍
  4. Android 获取手机存储信息详解(内存,外存等
  5. Delphi XE5 for Android(安卓)(七)
  6. Android智能手机搜索不到路由器无线信号
  7. 关于android的广播接收器(1)—基础篇
  8. Android的消息机制之Handler源码解析
  9. mac 系统下android源码下载以及使用(总结)
  10. Android NDK开发学习(一)