AsyncTask是一个抽象类,所以如果我们想使用它,就必须要创建一个子类去继承它。在继承时我们可以为AsyncTask类指定三个泛型参数,这三个参数的用途如下,如果不需要某个参数,可以设置为 Void
1. Params(参数类型)
在执行AsyncTask时需要传入的参数,可用于在后台任务中使用,是excute()任务执行方法和 doInBackground(Params...)的输入参数,通常为String
2. Progress(后台任务执行的进度类型)
后台任务执行时,如果需要在界面上显示当前的进度,则使用这里指定的泛型作为进度单位,是 onProgressUpdate(Progress...)和 publishProgress(Progress...)方法的参数,是一个数组类型的参数,一般为Integer
3. Result(返回的结果类型)
当任务执行完毕后,如果需要对结果进行返回,则使用这里指定的泛型作为返回值类型,是onPostExecute(Result)方法的输入参数
如果AsyncTask 确实不需要传递具体的参数,这三个泛型参数可以使用Void 替代。
AsyncTask 的声明如下所示:
public abstract class AsyncTask<Params, Progress, Result> {因此,一个最简单的自定义AsyncTask就可以写成如下方式:
class DownloadTask extends AsyncTask<Void, Integer, Boolean> { …… }
这里我们把AsyncTask的第一个泛型参数指定为Void,表示在执行AsyncTask的时候不需要传入参数给后台任务。第二个泛型参数指定为Integer,表示使用整型数据来作为进度显示单位。第三个泛型参数指定为Boolean,则表示使用布尔型数据来反馈执行结果。
1.execute(Parmas...parmas)
执行一个异步任务,需要我们在代码中调用此方法,触发异步任务的执行
2. onPreExecute()
执行在 UI 线程,在execute(Parmas...parmas)被调用后立即执行,这个方法会在后台任务开始执行之前调用,调用后立即执行,用于进行一些界面上的初始化操作,比如显示一个进度条对话框等。
3. doInBackground(Params...)
在线程池中执行,在onPreExecute() 完成后立即执行,这个方法中的所有代码都会在子线程中运行,我们应该在这里去处理所有的耗时任务。此方法将接收输入参数和返回计算结果,并将计算结果给onPostExecute 方法。在执行过程中可以调用 publishProgress(Progress...) 方法来更新任务进度信息。publishProgress 会调用 onProgressUpdate 方法。
4. onProgressUpdate(Progress...)
执行在 UI 线程,当在后台任务中调用了 publishProgress(Progress...) 方法后,这个方法就会很快被调用,直接将进度信息更新到 UI 组件上。
5. onPostExecute(Result)
执行在 UI 线程,当后台操作结束时,该方法被调用,doInBackground(Params...) 函数返回的计算结果将作为参数传递到此方法中,直接将结果显示到 UI 组件上。比如说提醒任务执行的结果,以及关闭掉进度条对话框等。
public class DownloadFilesTask extends AsyncTask<URL, Integer, Long> { //执行在线程池中 @Override protected Long doInBackground(URL... urls) { int count = urls.length; long totalSize = 0; for (int i = 0; i < count; i++) { totalSize += Downloader.downloadFile(urls[i]); publishProgress((int) (i / (float) count) * 100);//更新下载任务进度 if (isCancelled()) {//判断下载任务是否取消 break; } } return totalSize; } @Override protected void onProgressUpdate(Integer... progress) { setProgressPercent(progress[0]); } @Override protected void onPostExecute(Long result) { showDialog("Downloaded" + result + "bttes"); } }
new DownloadFilesTask().execute(url1,url2.url3);
3、不能在 doInBackground(Params...) 中更改 UI 组件信息
4、不要在程序中直接调用 onPreExecute()、onPostExecute()、doInBackground() 和 onProgressUpdate() 方法
5、一个任务实例只能执行一次,如果执行第二次将会抛出异常
6、在Android1.6 之前,AsyncTask 是串行执行任务的,在Android 1.6 AsyncTask 采用线程池里处理并行任务,但从Android 3.0 开始,为避免AsyncTask 所带来的并发错误,AsyncTask 又采用一个线程来串行执行任务。在Android 3.0 之后的版本中,我们仍然可以通过AsyncTask 的 executeOnExecutor 方法来并行的执行任务。
AsyncTask 的工作原理:
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR; public static final Executor SERIAL_EXECUTOR = new SerialExecutor(); @MainThread public final AsyncTask<Params, Progress, Result> execute(Params... params) { return executeOnExecutor(sDefaultExecutor, params); }
execute 方法会调用 executeOnExecutor 方法,源码如下所示:
private final WorkerRunnable<Params, Result> mWorker; @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;//将参数赋值给mWorker exec.execute(mFuture);//mFuture 会交给 SerialExecutor 的 execute 方法处理 return this; }在上述代码中,sDefaultExecutor 实际上是一个串行的线程池,一个进程中所有的AsyncTask 全部在这个串行的线程池中排队执行,在 executeOnExecutor 方法中,AsyncTask 的onPreExecute 方法最先执行,然后线程池开始执行,其执行过程如下所示:
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR; public static final Executor SERIAL_EXECUTOR = new SerialExecutor(); private static class SerialExecutor implements Executor { final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>(); Runnable mActive; public synchronized void execute(final Runnable r) { //将FutureTask 对象插入到任务队列 mTasks 中, mTasks.offer(new Runnable() { public void run() { try { r.run(); } finally { scheduleNext(); } } }); //如果当前没有正在活动的AsyncTask,则调用scheduleNext if (mActive == null) { scheduleNext(); } } protected synchronized void scheduleNext() { if ((mActive = mTasks.poll()) != null) {//执行下一个AsyncTask 任务 THREAD_POOL_EXECUTOR.execute(mActive); } } }
public static final Executor THREAD_POOL_EXECUTOR; private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();//CPU核心数 private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4));//核心线程数 private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;//最大线程数 private static final int KEEP_ALIVE_SECONDS = 30;//超时时间 private static final BlockingQueue<Runnable> sPoolWorkQueue = new LinkedBlockingQueue<Runnable>(128);//任务队列容量 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; }
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);//调用doInBackground 并获取返回值 Binder.flushPendingCommands(); } catch (Throwable tr) { mCancelled.set(true); throw tr; } finally { postResult(result);//调用postResult 方法,并将返回值作为参数传递过去 } 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); } } }; }
public FutureTask(Callable<V> callable) { if (callable == null) throw new NullPointerException(); this.callable = callable; this.state = NEW; // ensure visibility of callable } 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); } }
在mWorke 的call 方法中,首先将 mTaskInvoked 设未 true,表明当前任务已经被调用过了,然后执行AsyncTask的 doInBackground 方法,并将返回值传递给 postResult 方法,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 方法会通过 mHandler 发送一个 MESSAGE_POST_RESULT的消息,mHandler 的定义如下所示:
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; } } }
private void finish(Result result) { if (isCancelled()) { onCancelled(result); } else { onPostExecute(result); } mStatus = Status.FINISHED; }从上述代码可知,如果AsyncTask 被取消了,就调用 onCancelled 方法,否则就会调用 onPostExecute 方法,而onPostExecute 方法的参数就是 doInBackground 方法的返回值,以上就是AsyncTask 的整个工作过程。