首页 > 代码库 > Android开发之异步详解(二)之AsyncTask

Android开发之异步详解(二)之AsyncTask

  请尊重他人的劳动成果,转载请注明出处:Android开发之异步详解(二)之AsyncTask 

http://blog.csdn.net/fengyuzhengfan/article/details/40212745

        我曾在《Android开发之异步详解(一)之Thread+Handler》一文中介绍过通过Thread+Handler实现异步操作。感兴趣的朋友可以看一下。

        虽然Thread+Handler可以实现更新主线程的UI并实现异步,但Thread+Handler模式需要为每一个任务创建一个新的线程,任务完成后通过Handler实例向UI线程发送消息,完成界面的更新,这种方式对于整个过程的控制比较精细,但也是有缺点的,例如代码繁琐,在多个任务同时执行时,不易对线程进行精确的控制。

下面就介绍一下AndroidAsyncTask的使用:

 

AsyncTask简介:


        从Android 1.5开始系统将AsyncTask引入到android.os包中。AsyncTask,是android提供的轻量级的异步类,可以直接继承AsyncTask,在类中实现异步操作,并提供接口反馈当前异步执行的程度(可以通过接口实现UI进度更新),最后反馈执行的结果给UI主线程。


类概述:


        AsyncTask的出现使得使用UI线程变得轻巧而简单。这个类允许执行后台操作,并将操作结果更新到UI线程上而无需操作threads和handlers。

        AsyncTask的设计是围绕线程和Handler一个辅助类,并不构成一个通用线程框架。异步任务最好应采用短作业。如果你需要保持运行很长一段时间的线程,可以使用java.util.concurrent包等提供的ThreadPoolExecutor和FutureTask等各种API来替代。

        异步任务被定义运行在后台线程和要发布结果在UI线程上的一个运算。 异步任务被定义为ParamsProgressResult 3通用 类型,和onPreExecute,doInBackground,onProgressUpdateonPostExecute  4个步骤。

 

AsyncTask的定义


AsyncTask的定义了三种泛型类型 ParamsProgressResult

public  abstract  class  AsyncTask<Params, Progress, Result>

Params 启动任务执行的输入参数,比如HTTP请求的URL。

Progress 后台任务执行的进度。

Result 后台执行任务最终返回的结果,比如String。


AsyncTask中主要方法介绍:


onPreExecute() ,该方法将在执行实际的后台操作前被UI 线程调用。可以在该方法中做一些准备工作,如在界面上显示一个进度条,或者一些控件的实例化,这个方法可以不用实现。

doInBackground(Params...) ,将在onPreExecute 方法执行后马上执行,该方法运行在后台线程中。这里将主要负责执行那些很耗时的后台处理工作。可以调用 publishProgress方法来更新实时的任务进度。该方法是抽象方法,子类必须实现。

onProgressUpdate(Progress...) publishProgress(Progress...)方法被调用后,UI 线程将调用这个方法从而在界面上展示任务的进展情况,例如通过一个进度条进行展示。

onPostExecute(Result)在doInBackground 执行完成后,onPostExecute方法将被UI 线程调用,后台的计算结果将通过该方法传递到UI 线程,并且在界面上展示给用户。

onCancelled(),在用户取消线程操作的时候调用。在主线程中调用onCancelled()的时候调用。


使用AsyncTask的步骤


        AsyncTask允许你在你的用户界面上执行异步操作。它在一个子线程中执行耗时的操作,然后在UI线程上发布执行结果,而不需要你来处理Thread和Handler。

        要使用AsyncTask,你必须继承AsyncTask和实现doInBackground()回调方法,AsyncTask运行在后台的一个线程池中。若要更新你的UI,你应该实现onPostExecute()方法,它从doInBackground()方法中获取的结果,并运行在UI线程中,这样你就可以安全地更新你的UI你可以在UI线程中调用execute()方法开始你任务。


使用AsyncTask的步骤:

1)创建一个继承AsyncTask的类

2) 实现AsyncTask中定义的抽象方法doInBackground(Params...),然后根据需要重写它的其它方法。

3) 调用execute()来开始任务。

看一个例子:

// <String,Integer, Bitmap>
// 表示从调用位置传来的参数
// Integer:表示读取网络数据的进度
// 从网络返回的值
class NetTask extends AsyncTask<String, Integer, Bitmap> {
    private String path;
    private ImageView iv;
 
    public NetTask(String path, ImageView iv) {
       this.path = path;
       this.iv = iv;
    }
 
    // 主线程中,反馈网络访问进度
    @Override
    protected void onProgressUpdate(Integer... values) {
       super.onProgressUpdate(values);
       Log.i("NetUtil", "values=" + values[0]);
    }
 
    // 主线程中,子线程执行之前执行
    @Override
    protected void onPreExecute() {
       super.onPreExecute();
    }
 
    // 子线程
    @Override
    protected Bitmap doInBackground(String... params) {
       try {
           URL url = new URL(path);
           HttpURLConnection conn = (HttpURLConnection) url
                  .openConnection();
           // 设置一些连接属性
           conn.setConnectTimeout(5000);
           conn.setRequestMethod("GET");// POST
           // 设置http头信息
           //conn.setRequestProperty("Content-type", newValue)
           if (conn.getResponseCode() == 200) {
              InputStream is = conn.getInputStream();
              return BitmapFactory.decodeStream(is);
           }
       } catch (MalformedURLException e) {
           e.printStackTrace();
       } catch (IOException e) {
           e.printStackTrace();
       }
       return null;
    }
 
    // 在主线程中,网络返回数据时执行
    @Override
    protected void onPostExecute(Bitmap result) {
       super.onPostExecute(result);
       if (result != null) {
           iv.setImageBitmap(result);
       }
    }
}

注意事项:


为了正确的使用AsyncTask类,以下是几条必须遵守的准则:

1) AsyncTask的实例必须在UI 线程中创建。

2) execute方法必须在UI 线程中调用。

3) 不要手动的调用onPreExecute(),onPostExecute(Result),doInBackground(Params...), onProgressUpdate(Progress...)这几个方法,需要在UI线程中实例化这个AsyncTask来调用。

4) 该AsyncTask只能被执行一次,否则多次调用时将会出现异常。

5) doInBackground方法和onPostExecute的参数必须对应,这两个参数在AsyncTask声明的泛型参数列表中指定,第一个为doInBackground接受的参数,第二个为显示进度的参数,第第三个为doInBackground返回和onPostExecute传入的参数。


Thread+Handler模式与AsyncTask的优缺点:


AsyncTask实现的原理和适用的优缺点:

        AsyncTask,是android提供的轻量级的异步类,可以直接继承AsyncTask,在类中实现异步操作,并提供接口反馈当前异步执行的程度(可以通过接口实现UI进度更新),最后反馈执行的结果给UI主线程.

使用的优点:

1)        简单,快捷

2)        过程可控     

使用的缺点:

1)        在使用多个异步操作和并需要进行Ui变更时,就变得复杂起来.

 

Handler异步实现的原理和适用的优缺点:

        在Handler 异步实现时,涉及到 Handler,Looper, Message,Thread四个对象,实现异步的流程是主线程启动Thread(子线程)运行并生成Message-Looper获取Message并传递给HandlerHandler逐个获取Looper中的Message,并进行UI变更。

使用的优点:

1)        结构清晰,功能定义明确

2)        对于多个后台任务时,简单,清晰

使用的缺点:

1)         在单个后台异步处理时,显得代码过多,结构过于复杂(相对性)

最后需要说明AsyncTask不能完全取代线程,在一些逻辑较为复杂或者需要在后台反复执行的逻辑就可能需要Thread+Handler来实现了。

       如果你觉得这篇博文对你有帮助的话,请为这篇博文点个赞吧!也可以关注fengyuzhengfan的博客,收看更多精彩!http://blog.csdn.net/fengyuzhengfan/   

 

 

 

Android开发之异步详解(二)之AsyncTask