官方API翻译
AsyncTask使开发者可以更轻松的使用UI线程。这个类使开发者无需操作Thread
或Handler
便可执行后台操作并将结果返回到UI线程。
AsyncTask被设计为一个围绕Thread
和Handler
的辅助类,并且不构成通用线程框架。理论上AsyncTask应该被用于几秒钟的短作业,如果线程需要运行一段时间,强烈建议使用java.util.concurrent
包下的Excutor
、ThreadPoolExecutor
和FutureTask
。
异步任务是指运行在后台线程,而结果需要返回到UI线程的计算过程。异步任务由三个泛型:Params
、Progress
和Result
,以及四个步骤:调用onPreExecute
、doInBackground
、onProgressUpdate
、onPostExecute
组成。
用法
AsyncTask在使用前需要先被继承并覆盖doInBackground()
等方法。通常还会覆盖onPostExecute()
方法。
例如
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));
// Escape early if cancel() is called
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);
AsyncTask的泛型类型
异步任务用到的三种泛型类型如下:
1. Params
任务执行时需要传递的参数的类型。
1. Progress
后台运行期间返回的进度的类型。
1. Result
后台运行的返回结果的类型。
这三个泛型并非都会被用到,用Void
说明该泛型未被使用:
private class MyTask extends AsyncTask<Void, Void, Void> { ... }
四个步骤
每个异步任务的执行都需要经过4个步骤:
1. onPreExecute()
后台任务执行前在UI线程上的回调。一般用于初始化task并在界面上显示进度条。
1. doInBackground()
在后台线程被调用,在onPreExecute()
执行完后立即执行。这一步被用来在后台执行耗时操作。异步任务的参数在这里被传递进来。运算处理的结果会在这一步返回给最后一步。可以在此方法中调用publishProgress()
将进度返回给UI线程的onProgressUpdate()
1. onProgressUpdate()
在调用publishProgress()
之后被调用,运行在UI线程,其执行时间是不确定的。该方法用于后台任务运行时在用户界面显示进度。
1. onPostExecute()
后台任务结束后被调用,执行在UI线程。后台任务的结果会在这里以参数形式传递进来。
取消任务
可以通过调用cancle()
取消任务,之后如果调用isCancelled()
时会返回true。如果调用了cancle()
,在doInBackGround()
之后会执行onCancelled()
而不是onPostExcute()
。为了保证task尽快被取消,应该适时的在odInBackGround()
中调用isCancelled()
来获取当然task状态。
线程规则
一下是使用本类时必须遵守的几个线程规则
- AsyncTask必须在UI线程中被加载。
- AsyncTask实例必须在UI线程中创建。
- execute()
方法必须在UI线程中调用。
- 不能手动调用的方法:onPreExecute()
、onPostExecute()
、doInBackground()
、onProgressUpdate()
。
- 只能执行一次。(再次执行会抛异常)
可观察内存
AsyncTask保证所有回调都同步调用,因此下面的操作都是线程安全的。
- 在构造方法或onPreExecute()
中给成员赋值,然后在doInBackGroudn()
中使用。
- 在doInBackGround()
中赋值,然后在onProgressUpdate()和
onPostExecute()`中使用。
执行顺序
期初,多个AsyncTask连续的在同一个后台线程执行。DONUT之后,多个AsyncTask在线程池的不同线程中并行执行。HONEYCOMB之后,多个task在同一个线程执行避免并行执行引发的应用错误。
如果确实需要并行执行,可以用’THREAD_POOL_EXECUTOR’调用executeOnExecutor(java.util.concurrent.Executor,Object[])