美文网首页
源码分析AsyncTask的工作原理

源码分析AsyncTask的工作原理

作者: 空山Echo | 来源:发表于2019-05-23 15:00 被阅读0次

一、AsyncTask原理介绍

  • AsyncTask的实现原理 = 线程池+ Handler

其中:线程池用于线程调度,复用&执行任务; Handler用于异步通信

  • 其内部封装了2个线程池+ 1个Handler,具体介绍如下:
image

二、AsyncTask工作过程详解

包含使用execute与executeOnExecutor两种方式。

流程示意图:
image.png
无标题.png

AsyncTask.(Params... params)

1. 创建AsyncTask对象,并初始化

mHandler:更新UI,从主线程中获取
sHandler:用于执行过程中的线程切换
mFuture:是FutureTask对象是一个并发类,相当于Runnable的作用。将封装任务请求的参数,之后任务的具体执行内容就是在其run方法中实现
Api26+ 可以在主线程和子线程中创建对象

2.从调用execute方法开始,execute方法又会调用executeOnExecutor(sDefaultExecutor, params)方法
  • 其中的sDefaultExecutor就是AsyncTask内部的SerialExecutor对象
3. 在executeOnExecutor中主要完成如下工作
  1. FutureTask对象获取到任务请求的参数
  2. 调用onPreExecute方法,该方法运行在创建AsyncTask对象的线程
  3. 调用exec.execute(mFuture)方法
4. 此时的exec.execute,实际就是sDefaultExecutor.execute方法。
  • SerialExecutor是一个串行的线程池,一个进程中的AsyncTask都在这个串行的线程池中排队执行
5. 由此进入到线程池的排队执行的过程,通过分析SerialExecutor.execute 方法可以了解如下几点:
  1. synchornized execute (final Runnable r):synchornized 决定了串行执行方式;参数Runnable对象就是上述封装了请求参数的FutureTask对象
  2. execute方法首先将FutureTask对象添加到队列mTask中
  3. 如果此时没有正在活动的AsyncTask任务,则调用SerialExecutor的scheduleNext方法来执行下一个认为
  4. 同时一个任务执行完毕将执行下一个任务,知道所有任务都被执行为止。
6. SerialExecutor的scheduleNext方法的结构很简单,最终它调用THREAD_POOL_EXECUTOR.execute方法,由此进入真正的执行阶段。
  • 由上述可以看出AsyncTask中的两个线程池,SerialExecutor线程池用来任务的排队;THREAD_POOL_EXECUTOR线程池用于真正的执行任务
  • THREAD_POOL_EXECUTOR中的任务执行,遵循前面章节了解的ThreadPoolExecutor的执行过程
7. 我们知道任务请求参数被封装在FutureTask对象中,处理FutureTask对象的过程就是真正执行的部分。FutureTask的run方法会调用mWorker的call方法,最终在线程池中执行。来详细看看mWorker的run方法:
  1. 首先将当前任务标志成已调用
  2. 然后执行doInBackground方法,在此方法中可以调用publishProgress方法用来发送MESSAGE_POST_PROGRESS消息来更新任务执行进度
  3. 将2中的返回值传给postResult方法
  4. 在postResult方法中,将通过sHandler发送一个MESSAGE_POST_RESULT消息,并且携带返回结果即doInBackground方法的返回值
  5. sHandler收到这个消息后,获取返回结果并会调用AsyncTask的finish方法,执行过程这时候也从线程池回到了主线程
  6. finish方法先检查AsyncTask是否被取消,取消了就回调onCanceled方法,否则就调用onPostExecute方法并传入返回结果。

AsyncTask.executeOnExecutor(Executor exec,Params... params)

1. 创建AsyncTask对象,并初始化(同上)
2. 在executeOnExecutor中主要完成如下工作
  1. FutureTask对象获取到任务请求的参数
  2. 调用onPreExecute方法,该方法运行在创建AsyncTask对象的线程
  3. 调用exec.execute(mFuture)方法, 即THREAD_POOL_RESULT.execute(),由此就进入并行的执行方式
3. 之后同上7,调用mWorker的call方法执行任务。

源码展示

/**
     * Creates a new asynchronous task. This constructor must be invoked on the UI thread.
     *
     * @hide
     */
    public AsyncTask(@Nullable Looper callbackLooper) {
        mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper()
            ? getMainHandler()
            : new Handler(callbackLooper);

        mWorker = new WorkerRunnable<Params, Result>() {
            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<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);
                }
            }
        };
    }
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);
            }
        }
    }
 /**
     * This method can be invoked from {@link #doInBackground} to
     * publish updates on the UI thread while the background computation is
     * still running. Each call to this method will trigger the execution of
     * {@link #onProgressUpdate} on the UI thread.
     *
     * {@link #onProgressUpdate} will not be called if the task has been
     * canceled.
     *
     * @param values The progress values to update the UI with.
     *
     * @see #onProgressUpdate
     * @see #doInBackground
     */
    @WorkerThread
    protected final void publishProgress(Progress... values) {
        if (!isCancelled()) {
            getHandler().obtainMessage(MESSAGE_POST_PROGRESS,
                    new AsyncTaskResult<Progress>(this, values)).sendToTarget();
        }
    }
    private Result postResult(Result result) {
        @SuppressWarnings("unchecked")
        Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
                new AsyncTaskResult<Result>(this, result));
        message.sendToTarget();
        return result;
    }
 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;
            }
        }
    }

相关文章

  • AsyncTask工作原理

    AsyncTask工作原理调用图 AsyncTask工作原理源码分析,建议配合调用图一起看 调用 AsyncTas...

  • 源码分析AsyncTask的工作原理

    一、AsyncTask原理介绍 AsyncTask的实现原理 = 线程池+ Handler 其中:线程池用于线程调...

  • Android源码解析-Asynctask

    android源码分析-AsyncTask 我们一般创建一个AsyncTask的任务代码如下: 下面开始分析源码:...

  • AsyncTask异步任务类

    目录介绍 01.先看下AsyncTask用法 02.AsyncTask源码深入分析2.1 构造方法源码分析2.2 ...

  • AsyncTask工作原理分析

    AsyncTask 相信大家对他的使用并不陌生,它是谷歌官方提供的一种轻量级别的异步任务类,底层封装的是两个线程池...

  • AsyncTask源码分析

    前言 IntentService使用及源码分析 HandlerThread源码分析 AsyncTask使用及封装实...

  • AsyncTask 使用及封装实践

    前言 IntentService使用及源码分析 HandlerThread源码分析 AsyncTask使用及封装实...

  • AsyncTask的工作原理(源码剖析)

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

  • AsyncTask源码学习

    AsyncTask源码学习 AsyncTask的实现原理是通过Java中的线程池来的。 一、重要属性 AsyncT...

  • Android - AsyncTask (SDK 24)

    利用AsyncTask给ListView异步加载图片 实现图文混排 链接 AsyncTask源码分析 知乎

网友评论

      本文标题:源码分析AsyncTask的工作原理

      本文链接:https://www.haomeiwen.com/subject/bppdzqtx.html