【Android】AsyncTask源码解析

1 AsyncTask简介

AsyncTask<Params, Progress, Result>

  • Params:启动任务执行的输入参数,如doInBackground的输入参数
  • Progress:后台任务执行的百分比,如on
  • Result:后台任务执行最终返回的结果,比如doInBackground返回值类型以及onPostExecute的输入参数。
  1. execute(Params… params):执行一个异步任务,需要我们手动去调用此方法,触发异步任务的执行。
  2. onPreExecute():在execute(params… params)被调用后立即执行,一般用来在执行后台任务前做一些准备工作。
  3. doInBackground(Params… params):在onPreExecute()完成后立即执行,用于执行耗时操作,在执行过程中可以调用publishProgress(Progress… values)来更新进度信息。
  4. onProgressUpdate(Progress… values):在调用publishProgress(Progress… values)时,此方法被执行,直接将进度信息更新到UI组件上。
  5. onPostExecute(Result result):当后台操作结束时,此方法将会被调用,计算结果将作为参数传递到此方法中,直接将结果显示到UI组件上。

2 AsyncTask执行流程

按照AsyncTask执行顺序来,AsyncTask构造方法—>execute—>onPreExecute—>doInBackground、onProgressUpdate()—>onPostExecute

2.1 AsyncTask构造方法

    public AsyncTask() {
        this((Looper) null);
    }
	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);
                }
            }
        };
    }
	

这里实例化了一个Handler,WorkerRunnable和FutureTask对象,WorkerRunnable对象实现了Callable接口,如果没有指定Looper,则使用的是主线程的Looper

2.2 execute

    public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
    private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
    private volatile Status mStatus = Status.PENDING;//默认没有被执行

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

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

分析:调用execute方法时,会调用executeOnExecutor方法,该方法传入了两个参数,其中一个是sDefaultExecutor,该sDefaultExecutor被实例化为SerialExecutor对象。在executeOnExecutor方法里,首先判断AsyncTask状态,AsyncTask默认状态是未被执行,如下所示,AsyncTask状态有以下几种:

public enum Status {
        /**
         * Indicates that the task has not been executed yet.
         * 表示该任务还没有被执行
         */
        PENDING,
        /**
         * Indicates that the task is running.
         * 表示该任务正在被执行
         */
        RUNNING,
        /**
         * Indicates that {@link AsyncTask#onPostExecute} has finished.
         * 表示该任务已经被完成
         */
        FINISHED,
    }

2.3 onPreExecute

在executeOnExecutor判断,如果AsyncTask没有被执行,则执行接下来的操作;如果被执行了,则抛出异常。如果AsyncTask没有被执行,则将状态设置为运行中,并调用onPreExecute()方法,该方法是一个空的方法,具体内容需要自己重写,而且它是运行在主线程中的。

    @MainThread
    protected void onPreExecute() {
    }

2.4 doInBackground

在executeOnExecutor里,接下来继续执行,将execute传入的参数存放在mWorker.mParams中,mWorker是WorkerRunnable对象,实现了Callable接口,这里可以参考【线程创建的四种方式】中使用Callable和Future来创建线程。这里有些许不同,这里是通过线程池来加载FutureTask的。接下来执行exec.execute(mFuture);exec是executeOnExecutor传入的第一个参数,是SerialExecutor对象。所以调用的是SerialExecutor里的execute方法

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

该方法会将FutureTask存入一个双端数组队列中,然后从队列中取出FutureTask并交给threadPoolExecutor执行,关于线程池可以参考【Android 线程池原理及使用】

    static {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS,
                sPoolWorkQueue, sThreadFactory);
        threadPoolExecutor.allowCoreThreadTimeOut(true);
        THREAD_POOL_EXECUTOR = threadPoolExecutor;
    }

当线程池执行时,就会执行FutureTask,FutureTask会先执行WorkerRunnable的call方法,在call方法中调用doInBackground方法

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

当doInBackground执行完后,会调用postResult

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

在postResult中,会通过message.sendToTarget()将详细发送到MessageQueue中存储,接下来就是消息机制了,MessageQueue接收到消息后会将Message存入到消息队列中,然后如果Looper被阻塞,则唤醒Looper,Looper被唤醒后会无限循环从MessageQueue中取出消息,然后将取出的消息通过msg.target.dispatchMessage发送给执行的Handler进行处理,然后handler调用handleMessage处理消息,这段可参考【Android消息机制】

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

如上述代码所示,msg.what=MESSAGE_POST_PROGRESS时,调用onProgressUpdate方法,msg.what=MESSAGE_POST_RESULT时调用finish方法,该finish方法中将结果返回给onPostExecute方法

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

2.5 onPostExecute

onPostExecute方法是一个空方法,需要自己重写

    protected void onPostExecute(Result result) {
    }

3 流程总结

  1. AsyncTask初始化时会初始化一个Handler、WorkRunnable和FutureTask对象,该Handler默认调用的是主线程的Looper,WorkRunnable实现了Callable接口
  2. AsyncTask是用线程池来执行任务的。在调用execute方法时,会调用onPreExecute,然后调用ThreadPoolExecutor的execute方法来执行FutureTask,而WorkRunnable被传入到FutureTask中,因此会调用WorkRunnable里面的call方法。
  3. 在WorkRunnable里面的call方法中会执行doInBackground方法,且call方法最终会调用postResult方法,该方法中将最终结果封装到Message中,然后通过Message.sendToTarget最终将消息传入到消息队列中。
  4. Looper从MessageQueue中取出消息交给Handler处理,然后根据需求调用onPostExecute和onProgressUpdate。

4 细节

  1. AsyncTask的execute方法每次只能执行一次
  2. 使用的线程池,则可以复用线程池里的线程,减少了开销,提升了性能
发布了107 篇原创文章 · 获赞 142 · 访问量 13万+

猜你喜欢

转载自blog.csdn.net/u013293125/article/details/94719025