当Android的UI线程超过5s未响应时,系统会引发ANR(Application Not Responding)异常,所以一般不在UI线程中执行耗时任务。一般是在其他线程中处理耗时任务,然后及时更新UI界面。AsyncTask是异步任务,能够更简单地解决此类问题。

一、为什么使用AsyncTask

  为了避免在Android的主线程(UI线程)中处理耗时任务,通常是要建立一个新线程来处理耗时任务。但是,有时候我们需要一边处理任务一边及时更新UI组件,而问题出现了,非UI线程不能直接更新UI组件。Android为此提供了几种解决方法:

  1. 使用Handler实现线程之间的通信;

  2. 使用Activity.runOnUIThread(Runnable runnable);

  3. 使用View.post(Runnable runnable);

  4. 使用View.postDelayed(Runnable runnable, long time)。AsyncTask 简要介绍-LMLPHP

  这四种方法都使得编程较为繁琐,而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.方法执行过程

AsyncTask 简要介绍-LMLPHP

参考资料:

  • 1.  李刚 .疯狂Android讲义 :电子工业出版社 ,2013 :220-221 .

05-21 16:17