Params:启动任务执行的输入参数,如http请求的url
Progress:后台任务执行的百分比
Result:后台执行任务最终返回的结果类型
对应参数不处理设置成Void
public class DownLoadAsyncTask extends AsyncTask<String,Integer,Bitmap> { /** * onPreExecute是可以选择性覆写的方法 * 在主线程中执行,在异步任务执行之前,该方法将会被调用 * 一般用来在执行后台任务前对UI做一些标记和准备工作, * 如在界面上显示一个进度条。 */ @Override protected void onPreExecute() { super.onPreExecute(); } /** * 抽象方法必须覆写,执行异步任务的方法 * @param params * @return */ @Override protected Bitmap doInBackground(String... params) { return null; } /** * onProgressUpdate是可以选择性覆写的方法 * 在主线程中执行,当后台任务的执行进度发生改变时, * 当然我们必须在doInBackground方法中调用publishProgress() * 来设置进度变化的值 * @param values */ @Override protected void onProgressUpdate(Integer... values) { super.onProgressUpdate(values); } /** * onPostExecute是可以选择性覆写的方法 * 在主线程中执行,在异步任务执行完成后,此方法会被调用 * 一般用于更新UI或其他必须在主线程执行的操作,传递参数bitmap为 * doInBackground方法中的返回值 * @param bitmap */ @Override protected void onPostExecute(Bitmap bitmap) { super.onPostExecute(bitmap); } /** * onCancelled是可以选择性覆写的方法 * 在主线程中,当异步任务被取消时,该方法将被调用, * 要注意的是这个时onPostExecute将不会被执行 */ @Override protected void onCancelled() { super.onCancelled(); } }启动AsyncTask:
new DownLoadAsyncTask().execute();AsyncTask在具体的使用过程中也是有一些条件限制的,主要有如下几点:
AsyncTask的类必须在主线程中加载,这就意味着第一次访问AsyncTask必须发生在主线程,当然这个过程在Android 4.1及以上版本中已经被系统自动完成。在Android 5.0的源码中,可以查看 ActivityThread 的 main 方法,它会调用AsyncTask的init方法,这就满足了AsyncTask的类必须在主线程中进行加载这个条件了
AsyncTask的对象必须在主线程中创建
execute()必须在UI线程调用
不要在程序中直接调用 onPreExecute()、onPostExecute()、doInBackground() 和 onProgressUpdate()
一个AsyncTask对象只能执行一次,即只能调用一次 execute(),否则会报运行时异常
在Android 1.6之前,AsyncTask是串行执行任务,Android 1.6的时候AsyncTask开始采用线程池处理并行任务,但是从Android 3.0开始,为了避免AsyncTask所带来的并发错误,AsyncTask又采用了一个线程来串行执行任务。尽管如此,在Android 3.0以及后续版本中,仍然可以通过AsyncTask的 executeOnExecutor() 来并行执行任务
为了能够更清晰的理解AsyncTask的工作原理,在分析原理之前,有必要对AsyncTask的内部构造做一个简单的说明。
我们知道AsyncTask能在 doInBackground() 执行耗时操作,其中耗时操作会由内部的一个线程池 THREAD_POOL_EXECUTOR 处理, onProgressUpdate()、onPostExecute() 切回主线程更新UI,而切换回UI线程是通过Handler收发消息实现的。
从 execute() 开始分析,execute() 会调用 executeOnExecutor():
public final AsyncTask<Params, Progress, Result> execute(Params... params) { // sDefaultExecutor是一个串行的线程池 // 一个进程中所有的AsyncTask全部在这个串行的线程池中排队执行 return executeOnExecutor(sDefaultExecutor, params); } public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec, Params... params) { if (mStatus != Status.PENDING) { switch (mStatus) { case RUNNING: case FINISHED: // 抛异常 break; } } mStatus = Status.RUNNING; onPreExecute(); // 在执行耗时操作前就回调onPreExecute() mWorker.mParams = params; // WorkerRunnable的call()方法会在线程池中执行回调doInBackground() exec.execute(mFuture); // FutureTask,在构造中会传入在线程池执行耗时任务的mWorker return this; }接下来分析线程池的执行过程:
public static final Executor SERIAL_EXECUTOR = new SerialExecutor(); private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR; // SerialExecutor线程池用于任务的排队,实际执行的线程池是THREAD_POOL_EXECUTOR private static class SerialExecutor implements Executor { final ArrayDeque<Runnable> mTasks = new ArrayDeque<>(); Runnable mActive; // 在AsyncTask.executorOnExecutor()中的sDefaultExecutor.execute()调用该方法 // 传入的是AsyncTask的Params参数封装的FuterTask对象,是一个并发类充当Runnable public synchronized void execute(final Runnable r) { // 将Runnable存到队列中 mTasks.offer(new Runnable() { public void run() { try { // 从这里可以看出在一个AsyncTask任务执行完后才去拿下一个AsyncTask任务 // 调用FuterTask的run(),实际是调用的内部WorkerRunnable的call() r.run(); } finally { scheduleNext(); // 执行下一个AsyncTask任务 } } }); if (mActive == null) { scheduleNext(); } } protected synchronized void scheduleNext() { // 从队列中拿一个AsyncTaskr任务扔给线程池执行 if ((mActive == mTasks.poll()) != null) { // 实际的耗时操作是在线程池THREAD_POOL_EXECUTOR执行 THREAD_POOL_EXECUTOR.execute(mActive); } } }FutureTask 的 run() 会调用 mWorker 的 call() 方法,因此 mWorker 的 call() 最终会在线程池中执行,在AsyncTask构造方法中:
mWorker = new WorkerRunnable<Params, Result>() { public Result call() throws Exception { mTaskInvoked.set(true); // 设置标志表示当前任务已经被调用了 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); return postResult(doInBackground(mParams)); } }; mFuter = new FuterTask<Result>(mWorker) {...} private Result postResult(Result result) { Message message = sHandler.obtainMessage(MESSAGE_POST_RESULT, new AsyncTaskResult<Result>(this, result)); message.sendToTarget(); // 将doInBackground()的执行结果通过Handler发送切换回主线程更新UI return result; } private static final InternalHandler sHandler = new InternalHandler(); // 在线程池中获取的数据通过Handler从子线程切换回主线程更新UI // InternalHandler是静态成员在加载类的时候会初始化,因此这就要求AsyncTask必须在主线程中加载 private static class InternalHandler extends Handler { @Override public void handleMessage(Message msg) { AsyncTaskResult result = (AsyncTaskResult) msg.obj; switch (msg.what) { case MESSAGE_POST_RESULT: result.mTask.finish(result.mData[0]); // 回调AsyncTask的finish 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; } // FutureTask内部 public FutureTask(Runnable runnable) { this.callable = callable; this.state = NEW; } public void run() { try { Callable<V> c = callable; if (c != null && state == NEW) { V result; try { result = c.call(); // 调用的是WorkerRunnable的call() } catch (Throwable ex) {...} } } finally {...} }