1.AsyncTask概述
AsyncTask可以使UI线程使用得更加简单方便。这个类可以在UI线程后台执行操作和返回执行结果,而不需要多个线程或Handler等来处理程序。
AsyncTask是围绕线程和Handler设计出来的一个辅助类,并不能构成一个通用的线程框架。AsyncTask最好使用在时间较短的操作(至多不超过几秒钟)。如果你需要线程长时间运行,推荐您使用java.util.concurrent包中各种API,如Executor、ThreadPoolExecutor和FutureTask等类。
异步任务被定义为一种在线程后台运行和将运行结果返回UI线程的计算。异步任务定义了3个泛型参数:Params,Progress和Result,以及4个步骤:onPreExecute,doInBackground,onProgressUpdate和onPostExecute。
2.AsyncTask使用
首先,必须继承AsyncTask类。然后,由子类至少要覆盖doInBackground(params...)方法,经常也会覆盖onPostExecute(Result)方法。
子类实现例子如下:
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
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;
}
protected void onProgressUpdate(Integer... progress) {
setProgressPercent(progress[0]);
}
protected void onPostExecute(Long result) {
showDialog("Downloaded " + result + " bytes");
}
}
执行例子:
new DownloadFilesTask().execute(url1, url2, url3);
3.AsyncTask通用类型
以下是异步任务使用的三种类型:
Params,要发起执行的任务的参数类型
Progress,在后台运行时的进度单位类型
Result,返回后台运行结果的类型
注:如果异步任务不需要使用任何参数类型时,可以简单的使用Void类型标志,例如
public class MyAsyncTask extends AsyncTask<Void, Void, Void>{ ... }
4.AsyncTask四个步骤
当一个异步任务执行时,会经过以下4步:
onPreExecute(),该方法在UI线程执行异步任务之前调用。这步通常用来初始化任务,例如,在用户界面上显示一个进度条。
doInBackground(Params...),在后台线程执行onPreExecute()结束后随即调用该方法。这步用于后台运行,可能需要很长时间。异步任务的参数就是被传递到这一步。运行后的结果必须是返回到这步或传递至下一步中。这步中还可以使用publishProgress(Progress...)函数更新一个或多个单位的实时进度。在onProgressUpdate(Progress...)这步中,这些值可以用于更新UI线程。
onProgressUpdate(Progress...),在publishProgress(Progress...)之后,UI线程调用该方法。执行的时间无法确定。当后台操作还在执行时,该方法可以在用户界面上以任何形式显示进度。例如,它可以使用动画进度条或在text字段中显示日志。
onPostExecute(Result...),在UI线程后台计算后调用。后台运行结果通过这一步传递的。
5.取消任务
在任何时候调用cancel(boolean)函数,就可以取消该任务。调用该方法后isCancelled()函数将会返回true.之后调用onCancelled(Object)方法,而不是在doInBackground(Object[])返回之后调用onPostExecute(Object).为了确保任务可以尽快取消,应该在doInBackground(Object[])中反复地检查isCancelled()返回值。
6.线程规则
必须要遵循以下几个线程规则,这个类才能正常地工作:
- AsyncTask类必须在UI线程加载。
- 任务实例必须在UI线程创建。
- execute(Params...)必须在UI线程上调用
- 别手动调用onPreExecute()、doInBackground(Params...)、onPostExecute(Result...)、onProgressUpdate(Progress..)
- 任务只能执行一次,如果企图多次执行,将会抛出一个异常。