当Android的UI线程超过5s未响应时,系统会引发ANR(Application Not Responding)异常,所以一般不在UI线程中执行耗时任务。一般是在其他线程中处理耗时任务,然后及时更新UI界面。AsyncTask是异步任务,能够更简单地解决此类问题。
一、为什么使用AsyncTask
为了避免在Android的主线程(UI线程)中处理耗时任务,通常是要建立一个新线程来处理耗时任务。但是,有时候我们需要一边处理任务一边及时更新UI组件,而问题出现了,非UI线程不能直接更新UI组件。Android为此提供了几种解决方法:
使用Handler实现线程之间的通信;
使用Activity.runOnUIThread(Runnable runnable);
使用View.post(Runnable runnable);
使用View.postDelayed(Runnable runnable, long time)。
这四种方法都使得编程较为繁琐,而AsyncTask是异步任务能够简化这些操作,适用于简单的异步处理,而不需要借助线程和Handler。
二、AsyncTask的基本知识
1. 三种参数类型
AsyncTask<>是抽象类,一般用于被继承,继承时需要指定三个参数,AsyncTask<Params,Progress, Result>,是三种泛型类型:
a. Params是启动任务执行的输入参数类型;
b. Progress是后台任务完成的进度值的类型,如进度百分比;
c. Result是后台任务完成后的返回值类型。
2. 使用AsyncTask
使用AsyncTask只需要三个步骤:
a. 继承AsyncTask,指定三个参数,如果泛型参数不需要指定,则可以设置为Void,如:
public class DownloadTask extends AsyncTask<Uri,Integer,String> {
...
}
b. 根据业务需求,重写AsyncTask的方法,AsyncTask方法如下:
1)doInBackground(Params ...):会在单独的后台线程中执行方法中的任务,是必须实现的方法,该方法 可以调用publishProgress(Progress.. value)来更新任务进度;
2)onProgressUpdate(Progress...):在doInBackground()方法调用publishProgress(Progress.. value)更 新任务进度之后将会自动调用该方法;如果在doInBackground()方法中没有调用publishProgress()方 法,则不会调用该方法;
3)onPreExecute():在doInBackground()方法调用之前被自动调用,即在耗时任务之前调用,主要用于 完成初始化,如现实进度条;
4)onPostExecute(Result...):当doInBackground()方法完成之后系统会自动调用该方法,并将 doInBackground()的返回值作为该方法的输入参数。
以上四个方法均不需要设计人员手工调用,系统会自动调用。除了doInBackground()方法以外,其他方法均能更新UI组件。以上方法并不是都要实现,但是至少实现doInBackground()方法和onPostExecute()方法。
c. 实例化AsyncTask的之类,并调用execute(Params ... params)方法,开始执行耗时任务。
3. 使用AsyncTask应该遵守的规则:
a. 必须在UI线程中创建AsyncTask之类实例;
b. 必须在UI线程中调用AsyncTask的execute方法;
c.doInBackground(Params ...)、onProgressUpdate(Progress...)、onPreExecute()和onPostExecute (Result...)这些方法不能由程序员自己调用,Android系统会自动调用;
d. 每个AsyncTask只能被执行一次,多次调用将会引发异常。
4.方法执行过程
参考资料:
1. 李刚 .疯狂Android讲义 :电子工业出版社 ,2013 :220-221 .