参考:http://blog.csdn.net/cnnumen/article/details/8437666
http://rainbow702.iteye.com/blog/1154918
AsyncTask是Android框架提供的异步处理的辅助类,它可以实现耗时操作在其他线程执行,而处理结果在Main线程执行,对于开发者而言,它屏蔽掉了多线程和后面要讲的Handler的概念。你不了解怎么处理线程间通讯也没有关系,AsyncTask体贴的帮你做好了。使用他你会发现你的代码很容易被理解,因为他们都有一些具有特定职责的方法,尤其是AsyncTask,有预处理的方法onPreExecute,有后台执行任务的方法doInBackground,有更新进度的方法publishProgress,有返回结果的方法onPostExecute等等,这就不像post这些方法,把所有的操作都写在一个Runnable里。不过封装越好越高级的API,对初级程序员反而越不利,就是你不了解它的原理。当你需要面对更加复 杂的情况,而高级API无法完成得很好时,你就杯具了。所以,我们也要掌握功能更强大,更自由的与Main线程通讯的方法:Handler的使用。
AsyncTask 的优势体现在解决了下面的问题:
•线程的开销较大,如果每个任务都要创建一个线程,那么应用程序的效率要低很多;
•线程无法管理,匿名线程创建并启动后就不受程序的控制了,如果有很多个请求发送,那么就会启动非常多的线程,系统将不堪重负。
•另外,前面已经看到,在新线程中更新UI还必须要引入handler,这让代码看上去非常臃肿。
AsyncTask是抽象类, 使用时需要派生一个子类, 如下:
public class QAsyncTask extends AsyncTask<Params, Progress, Result> { }
AsyncTask定义了三个泛型数据Params,Progress和Result, 作用如下:
Params:启动task时传入的参数, 如new QAsyncTask().execute(Params), 这个输入参数是task执行过程中的调用函数doInBackground(Params)的输入参数
Progress:后台任务执行的百分比, 他通过publicProgress(Progress)传给task执行过程中调用的函数onProgressUpdate(Progress)
Result:当后台线程执行完后输出给UI线程的数据类型,它是task执行过程中调用的函数onPostExecute(Result)的输入参数
AsyncTask子类必须重写的方法
1. onPreExecute();该方法将在执行实际的后台操作前被UI thread调用。可以在该方法中做一些准备工作,比如加载几张默认的预览图
2. doInBackground(Params...); 将在onPreExecute 方法执行后马上执行,该方法运行在后台线程中。这里将主要负责执行那些耗时的后台工作。
3. onProgressUpdate(Progress...);在publishProgress方法被调用后,这个方法将被UI线程调用, 用于更新进度等界面显示。
4. onPostExecute(Result);在doInBackground 执行完成后,onPostExecute 方法将被UI thread调用,后台的计算结果将通过该方法传递到UI thread.
为了正确的使用AsyncTask类,以下是几条必须遵守的准则:
1) Task的实例必须在UI thread中创建
2) execute方法必须在UI thread中调用
3) 不要手动的用onPreExecute(), onPostExecute(Result),doInBackground(Params...), onProgressUpdate(Progress...)这几个方法
4) 该task只能被执行一次,否则多次调用时将会出现异常
AsyncTask注意点:
在官方文档中指出, AsyncTasks should ideally be used for short operations, 就是说asyncTask执行的任务应该是一些短时间内可以完成的任务, 因为在android3.0之后, 默认情况下, 同一时间只能有一个asyncTask在运行, 也就是说所有的task都是串行运行的。所以如果某个task执行时间很长, 会导致后面的task长时间等待, 当然也可以通过调executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR), 可以同时运行5个task, 具体用法可以参考:
http://blog.csdn.net/hitlion2008/article/details/7983449
下面通过一个示例来解释说明。这个示例的大概流程是这样的,点击主Activity中的 "Download",弹出一个提示框,告知用户当前正在下载文件。下载过程中用户可以取消下载。下面给出截图:
点击上面的 Download ,会启动一个 AsyncTask 来模拟文件下载
若此时点击上面的 Cancel,则会调用 AsyncTask 的 cancel() 方法来取消该 task,提示框也会随之被取消(因为是基于 AlertDialog 的,所以不管点击哪个按钮,该提示框都会消失)
直至下载完成:
此时, OK 处于激活状态,表明下载已经完成。整个过程,不仅进度条在变化,它下面的提示信息也在变化。
public class MyAsyncTask extends AsyncTask<Integer, Integer, Boolean> { @Override protected void onPreExecute() { super.onPreExecute(); updateLog("AsyncTask started"); } @Override protected Boolean doInBackground(Integer... params) { int max = params[0]; for (int i = 0; i < max; i++) { try { publishProgress((int) (((i + 1.0) / max) * 100)); // 每隔一秒钟执行一次,模拟下载文件 Thread.sleep(1000); } catch (InterruptedException e) { return false; } } return true; } @Override protected void onProgressUpdate(Integer... values) { super.onProgressUpdate(values); dlProgress.setProgress(values[0]); updateLog(log.getText() + "."); } @Override protected void onPostExecute(Boolean result) { super.onPostExecute(result); taskOver = true; positiveBtn.setEnabled(true); negativeBtn.setEnabled(false); if (result) { updateLog("AsyncTask ended. Download successfully"); } else { updateLog("AsyncTask ended. Download failed"); } } @Override protected void onCancelled() { super.onCancelled(); taskOver = true; positiveBtn.setEnabled(true); negativeBtn.setEnabled(false); updateLog("AsyncTask cancelled"); } }AsyncTask必须在UI线程中创建,