上篇文章我们讲了Android中实现异步机制方式之一-----Handler方式,这一章我们来讲第二种方式----异步类AsyncTask
前面我们了解到Handler方式实现异步还是比较复杂的,不是特别容易理解。而AsycTask方式相对来说就要方便简单多了。先来看一下AsyncTask的一般模式:
private class MyAsyncTask extends AsyncTask<Void, Integer, Void> { @Override protected void onPreExecute() { // 用于完成对UI的一些标记和一些准备工作。 } @Override protected Void doInBackground(Void... params) { // doInBackground()用于执行比较耗时的操作,如网络图片的获取. // 调用publishProgress方法来更新进度 publishProgress(Integer... values); return null; } @Override protected void onProgressUpdate(Integer... values) { // 在调用publishProgress(Integer... values)时,此方法被执行,直接将进度信息更新到UI组件上 } @Override protected void onPostExecute(Void result) { // 进行数据加载完成后的UI操作 } }
这样就实现了异步操作,与Handler方式相比,是不是简单了许多呢?总结下来,一个异步任务的执行一般包括以下几个步骤:
1. execute(Params... params),执行一个异步任务,需要我们在代码中调用此方法,触发异步任务的执行。
2. onPreExecute(),在execute(Params... params)被调用后立即执行,一般用来在执行后台任务前对UI做一些标记和做一些准备工作。
3. doInBackground(Params... params),在onPreExecute()完成后立即执行,用于执行较为费时的操作,此方法将接收输入参数和返回计算结果。在执行过程中可以调用publishProgress(Progress...values)来更新进度信息。
4. onProgressUpdate(Progress... values),在调用publishProgress(Progress...values)时,此方法被执行,直接将进度信息更新到UI组件上。
5. onPostExecute(Result result),当后台操作结束时,此方法将会被调用,计算结果将做为参数传递到此方法中,直接将结果显示到UI组件上。
下面来浅谈一下AsyncTask类中多线程的处理机制。
AsyncTask类实现多线程背后其实是有一个线程池作为支撑的。
private static final int CORE_POOL_SIZE = 5; private static final int MAXIMUM_POOL_SIZE = 128; private static final int KEEP_ALIVE = 1; private static final ThreadFactory sThreadFactory = new ThreadFactory() { private final AtomicInteger mCount = new AtomicInteger(1); public Thread newThread(Runnable r) { return new Thread(r, "AsyncTask #" + mCount.getAndIncrement()); } }; private static final BlockingQueue<Runnable> sPoolWorkQueue = new LinkedBlockingQueue<Runnable>(10); /** * An {@link Executor} that can be used to execute tasks in parallel. */ public static final Executor THREAD_POOL_EXECUTOR = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);
这个线程池最多只是128个工作线程,等待队列设置为10.值得一提的是在Android3.0之前。如果并发线程超过138个(128个工作线程再加上10个阻塞线程)这是会抛出RejectedExecutionEXception. 而到了Android3.0以后不再是最多128个线程并发执行,而全部是单线程执行。因此不会出现这种异常。