AsyncTask 的使用和注意的问题

AsyncTask 算是我们比较经常使用的一个系统类了,我们知道费UI 线程是不能更新UI 的,当我们做一些耗时的操作只能借助Handler,Looper 来实现,比如我们从网络下载东西,想要进度条来更新,自己实现会很麻烦。然而使用AsyncTask 处理起来会非常轻松。
它来做一些异步处理的请求,然后可以很轻松地更新UI。
它是一个抽象类,就说明它是不具体的,我们要使用它,肯定要实现他的抽象方法。
我们继承会发现AsyncTask 枚举有三个不同的变量,这个我们可以跟着他的不同的方法的参数和返回值来一块看会更加清晰。

onPreExecute():在执行任务之前可以做一些初始化操作。
Result doInBackground(Params…):唯一的一个抽象方法,我们可以在这个方法执行耗时的操作。然后可以来更新UI。
onPostExecute(Result result()):doInBackground() 方法的返回值会传给方法的参数。doInBackground() 执行完执行此方法。
publishProgress(Progress… values):在doInBackground() 方法中调用此方法,比如下载东西会随着下载的进度一直变化,将参数传给onProgressUpdate 方法,可以在onProgressUpdate 方法中更新的UI。
onProgressUpdate(Progress… values):更新UI。
execute(Params…):最后调用此方法就开始执行了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

class Task extends AsyncTask<String, Integer, Bitmap>() {
@Override
protected void onPreExecute() {
super.onPreExecute();
}

@Override
protected Bitmap doInBackground(String... params) {
for (int i = 0; i < 100; i++) {
try {
Thread.sleep(500);
publishProgress(i);
} catch (InterruptedException e) {
e.printStackTrace();
Thread.interrupted();
}
}
return null;
}

@Override
protected void onPostExecute(Bitmap bitmap) {
super.onPostExecute(bitmap);
}

@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
AsyncActivity.mProgressBar.setProgress(values[0]);
}

@Override
protected void onCancelled(Bitmap bitmap) {
super.onCancelled(bitmap);
bitmap.recycle();
}

};
1
new Task().execute(str);

cancel(boolean):可以随时取消任务。
isCancelled():判断任务是否取消
onCancelled(Result result):doInBackground() 执行完成后,并且cancel() 之后执行。

除了doInBackground() 方法,其他都是执行在UI 线程的。而doInBackground() 执行完可以来更新UI。

AsyncTask 中几个重要的概念
AsyncTask 的原理是当多个任务,有一个默认的线程池SerialExecutor 来执行异步任务,然后在 子线程执行doInBackground 方法,
AsyncTaskResult 一个持有AsyncTaskResult 持有AsyncTask,Result,然后通过Handler 发送AsyncTaskResult 对象再来更新UI 线程。
FutureTask :异步任务的取消和获取结果
ThreadPoolExecutor:默认的一个线程池,你也可以使用executeOnExecutor() 方法传入自定义的线程池。

问题以及缺陷

默认线程池设定的又最大线程数,一旦超出(默认为128)再提交任务,将会抛出RejectedExecutionException。
内存泄露:AsyncTask 使用线程池来处,线程的声明周期是很不稳定,而且还要用来更新UI,一旦Activity 被destoy,将会造成内存泄露。所以使用时要讲持有对象使用弱引用。

参考


http://blog.csdn.net/guolin_blog/article/details/11711405
http://www.cnblogs.com/dolphin0520/p/3949310.html
http://blog.csdn.net/amurocrash/article/details/50876229
http://developer.android.com/intl/zh-cn/reference/android/os/AsyncTask.html
http://www.cnblogs.com/dolphin0520/p/3949310.html