企业🤖AI Agent构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
[TOC] 关于 Android 源码分析,引用郭霖老师博客的一段话: > 简单概括就是八个字:抽丝剥茧、点到即止。应该认准一个功能点,然后去分析这个功能点是如何实现的。但只要去追寻主体的实现逻辑即可,千万不要试图去搞懂每一行代码都是什么意思,那样很容易会陷入到思维黑洞当中,而且越陷越深。因为这些庞大的系统都不是由一个人写出来的,每一行代码都想搞明白,就会感觉自己是在盲人摸象,永远也研究不透。如果只是去分析主体的实现逻辑,那么就有比较明确的目的性,这样阅读源码会更加轻松,也更加有成效。 本文不是原创,是在阅读了互联网上各位大神关于 AsyncTask 源码分析的文章后,自己对于 AsyncTask 进行的一遍分析,虽不是原创,但自己顺着思路捋一遍,并敲下本文后,感觉对于 AsyncTask 的用法以及原理的理解更加深刻了。 本文参考资料: [Android中AsyncTask使用详解–孙群](http://blog.csdn.net/iispring/article/details/50639090) [Android异步任务AsyncTask的使用与原理分析–开心阳](http://blog.csdn.net/shakespeare001/article/details/51720548) [Android AsyncTask完全解析,带你从源码的角度彻底理解–郭霖](http://blog.csdn.net/guolin_blog/article/details/11711405) AsyncTask 的基础使用 AsyncTask 是一个抽象类,必须写一个子类继承它,在子类中完成异步操作。AsyncTask 抽象类指定了3个泛型类型参数: ```java public abstract class AsyncTask<Params, Progress, Result> { ... } ``` 三个泛型类型参数的含义如下: * Params:开始异步任务执行时传入的参数类型,即 doInBackground()方法中的参数类型; * Progress:异步任务执行过程中,返回进度值的类型,即在 doInBackground 中调用 publishProgress()时传入的参数类型; * Result:异步任务执行完成后,返回的结果类型,即 doInBackground()方法的返回值类型; AsyncTask 的回调方法包括: * onPreExecute():在执行后台操作之前调用,运行在主线程中; * doInBackground():核心方法,执行后台操作的方法,必须实现的一个方法,运行在子线程中; * onPostExecute():后台操作完成后调用,运行在主线程中; * onProgressUpdate():在下载操作 doInBackground()中调用 publishProgress()时的回调方法,用于更新下载进度,运行在主线程中; # 使用注意事项 * 对于一个 AsyncTack 的实例,只能执行一次 execute 方法,在该实例上第二次执行 execute 方法时就会抛出异常。 * AsyncTask 在最早的版本中用一个单一的后台线程串行执行多个 AsyncTask 实例的任务,从 Android 1.6(DONUT)开始,AsyncTask 用线程池并行执行异步任务,但是从Android 3.0(HONEYCOMB)开始为了避免并行执行导致的常见错误,AsyncTask 又开始默认用单线程作为工作线程处理多个任务。 从Android 3.0开始 AsyncTask 增加了 executeOnExecutor 方法,用该方法可以让 AsyncTask 并行处理任务,该方法的方法签名如下所示: ```java public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec, Params... params) ``` 第一个参数表示 exec 是一个 Executor 对象,为了让 AsyncTask 并行处理任务,通常情况下我们此处传入 AsyncTask.THREAD_POOL_EXECUTOR 即可,AsyncTask.THREAD_POOL_EXECUTOR 是 AsyncTask 中内置的一个线程池对象,当然我们也可以传入我们自己实例化的线程池对象。第二个参数 params 表示的是要执行的任务的参数。 # 整体流程 1、首先调用 AsyncTask 的构造方法,构造时对 Handler、WorkerRunnable(Callable) 和 FutureTask 进行初始化 2、然后调用 AsyncTask 的 execute 方法(可以手动设置 Executor,不设置则使用系统默认的 SerialExecutor) 3、首先判断当前 AsyncTask 状态,正在运行或者已经运行过就退出 4、调用 onPreExecute 执行准备工作 5、由 Executor 调用 FutureTask 的 run 方法,在 WorkerRunnable 中执行了 doInBackground 6、依旧是在 WorkerRunnable 中,调用 postResult,将执行结果通过 Handler 发送给主线程;调用 publishProgress 时,也是通过 Handler 将消息发送到主线程的消息队列中 # 源码解析 开始一个 AsyncTask 任务很简单,只要执行 new AsyncTask().execute()方法即可。我们的源码分析也从这里开始。 首先来看 AsyncTask 的构造函数: ```java /** * 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); 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); } } }; } ``` 可以看到,在构造函数中,初始化了两个变量 mWorker 和 mFuture。首先看看 AsyncTask 的 execute()方法。 ```java @MainThread public final AsyncTask<Params, Progress, Result> execute(Params... params) { return executeOnExecutor(sDefaultExecutor, params); } ``` 很简单,在主线程进行调用,返回 executeOnExecutor(sDefaultExecutor, params)方法的值,那么我们看看这个方法: ```java @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; } ``` 可以看到,首先对 AsyncTask 的状态进行了判断,当 AysncTask 的状态是 RUNNING 和 FINISHED 时,会抛出异常,这也是为什么一个任务实例只能被启动一次的原因。executeOnExecutor()方法传入两个参数,一个是 Executor,一个是 Params。Params 就是我们执行 doInBackground 中的参数类型。那么 Executor 呢,可以在上一段代码看到,传递来的参数是 sDefaultExecutor,它的初始化如下: ```java public static final Executor SERIAL_EXECUTOR = new SerialExecutor(); private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR; ``` 在 executeOnExecutor 方法中我们可以看到,先执行了 onPreExecute()方法,是在主线程。接着执行 exec.execute(mFuture),那么 doInBackground()方法应该就和它有关系了。接下来看看 SerialExecutor 类的 execute 方法,源码如下: ```java public synchronized void execute(final Runnable r) { mTasks.offer(new Runnable() { public void run() { try { r.run(); } finally { scheduleNext(); } } }); if (mActive == null) { scheduleNext(); } } ``` 可以看到,其中执行了参数 Runnable 的 run() 方法,这个 Runnable 就是传进来的 mFuture。那么看看 FutureTask 的 run()方法: ```java public void run() { if (state != NEW || !U.compareAndSwapObject(this, RUNNER, 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); } } ``` 在 run() 方法中执行了 Callable 的 call()方法,callable 又是谁呢,callable 就是在 FutureTask 初始化时传进来的 mWorker。说明调用的是 mWorker 的 call()方法。去看看: ```java 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(result),这其中又做了什么呢: ```java private Result postResult(Result result) { @SuppressWarnings("unchecked") Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT, new AsyncTaskResult<Result>(this, result)); message.sendToTarget(); return result; } ``` 查看源码得知,getHandler()返回的是 InternalHandler 的实例对象,那么就要去看看 InternalHandler 的 handleMessage()方法了。 ```java 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_RESULT 时,代表工作线程的任务执行完成,执行 finish()方法。what 值为 MESSAGE_POST_PROGRESS 时,执行 onProgressUpdate(),也就是调用 publishProgress()时的回调方法。看一看 finish() 方法: ```java private void finish(Result result) { if (isCancelled()) { onCancelled(result); } else { onPostExecute(result); } mStatus = Status.FINISHED; } ``` 当前任务被取消时,调用 onCancelled()方法,否则调用 onPostExecute()方法。最后看一下 publishProgress()的源码: ```java @WorkerThread protected final void publishProgress(Progress... values) { if (!isCancelled()) { getHandler().obtainMessage(MESSAGE_POST_PROGRESS, new AsyncTaskResult<Progress>(this, values)).sendToTarget(); } } ``` 至此,主要的源码就看完了,可以看到 AsyncTask 是对 Handler、Message 机制的一种封装,使得我们的调用更加简洁。