AsyncTask的使用

     参考:http://blog.csdn.net/cnnumen/article/details/8437666

http://rainbow702.iteye.com/blog/1154918

   AsyncTask是Android框架提供的异步处理的辅助类,它可以实现耗时操作在其他线程执行,而处理结果在Main线程执行,对于开发者而言,它屏蔽掉了多线程和后面要讲的Handler的概念。你不了解怎么处理线程间通讯也没有关系,AsyncTask体贴的帮你做好了。使用他你会发现你的代码很容易被理解,因为他们都有一些具有特定职责的方法,尤其是AsyncTask,有预处理的方法onPreExecute,有后台执行任务的方法doInBackground,有更新进度的方法publishProgress,有返回结果的方法onPostExecute等等,这就不像post这些方法,把所有的操作都写在一个Runnable里。不过封装越好越高级的API,对初级程序员反而越不利,就是你不了解它的原理。当你需要面对更加复 杂的情况,而高级API无法完成得很好时,你就杯具了。所以,我们也要掌握功能更强大,更自由的与Main线程通讯的方法:Handler的使用


     AsyncTask 的优势体现在解决了下面的问题:

线程的开销较大,如果每个任务都要创建一个线程,那么应用程序的效率要低很多; 
线程无法管理,匿名线程创建并启动后就不受程序的控制了,如果有很多个请求发送,那么就会启动非常多的线程,系统将不堪重负。 
另外,前面已经看到,在新线程中更新UI还必须要引入handler,这让代码看上去非常臃肿。



     AsyncTask是抽象类, 使用时需要派生一个子类, 如下:

public class QAsyncTask extends  AsyncTask<Params, Progress, Result> {
}

     AsyncTask定义了三个泛型数据ParamsProgressResult, 作用如下: 
           Params:
启动task时传入的参数, 如new QAsyncTask().execute(Params), 这个输入参数是task执行过程中的调用函数doInBackground(Params)的输入参数

           Progress后台任务执行的百分比, 他通过publicProgress(Progress)传给task执行过程中调用的函数onProgressUpdate(Progress)

           Result:当后台线程执行完后输出给UI线程的数据类型,它是task执行过程中调用的函数onPostExecute(Result)的输入参数



AsyncTask子类必须重写的方法

1. onPreExecute();该方法将在执行实际的后台操作前被UI thread调用。可以在该方法中做一些准备工作,比如加载几张默认的预览图

2. doInBackground(Params...); 将在onPreExecute 方法执行后马上执行,该方法运行在后台线程中。这里将主要负责执行那些耗时的后台工作。

3. onProgressUpdate(Progress...);publishProgress方法被调用后,这个方法将被UI线程调用, 用于更新进度等界面显示。

4. onPostExecute(Result);doInBackground 执行完成后,onPostExecute 方法将被UI thread调用,后台的计算结果将通过该方法传递到UI thread. 


  为了正确的使用AsyncTask类,以下是几条必须遵守的准则: 
 1) Task的实例必须在UI thread中创建 
 2) execute方法必须在UI thread中调用 
 3) 不要手动的用onPreExecute(), onPostExecute(Result)doInBackground(Params...), onProgressUpdate(Progress...)这几个方法 
 4) task只能被执行一次,否则多次调用时将会出现异常 
   


AsyncTask注意点:

  在官方文档中指出, AsyncTasks should ideally be used for short operations 就是说asyncTask执行的任务应该是一些短时间内可以完成的任务, 因为在android3.0之后, 默认情况下, 同一时间只能有一个asyncTask在运行, 也就是说所有的task都是串行运行的。所以如果某个task执行时间很长, 会导致后面的task长时间等待, 当然也可以通过调executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR) 可以同时运行5task, 具体用法可以参考:

http://blog.csdn.net/hitlion2008/article/details/7983449




下面通过一个示例来解释说明。这个示例的大概流程是这样的,点击主Activity中的 "Download",弹出一个提示框,告知用户当前正在下载文件。下载过程中用户可以取消下载。下面给出截图:

AsyncTask的使用_第1张图片

 

点击上面的 Download ,会启动一个 AsyncTask 来模拟文件下载


AsyncTask的使用_第2张图片

 

若此时点击上面的 Cancel,则会调用 AsyncTask 的 cancel() 方法来取消该 task,提示框也会随之被取消(因为是基于 AlertDialog 的,所以不管点击哪个按钮,该提示框都会消失)


AsyncTask的使用_第3张图片
 
 重新执行第一步,期间不点击 Cancel 按钮

AsyncTask的使用_第4张图片
 

直至下载完成:

AsyncTask的使用_第5张图片
 

此时, OK 处于激活状态,表明下载已经完成。整个过程,不仅进度条在变化,它下面的提示信息也在变化。

public class MyAsyncTask extends AsyncTask<Integer, Integer, Boolean> {

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        updateLog("AsyncTask started");
    }

    @Override
    protected Boolean doInBackground(Integer... params) {
        int max = params[0];
        for (int i = 0; i < max; i++) {
            try {
                publishProgress((int) (((i + 1.0) / max) * 100));
                // 每隔一秒钟执行一次,模拟下载文件
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                return false;
            }
        }
        return true;
    }

    @Override
    protected void onProgressUpdate(Integer... values) {
        super.onProgressUpdate(values);
        dlProgress.setProgress(values[0]);
        updateLog(log.getText() + ".");
    }

    @Override
    protected void onPostExecute(Boolean result) {
        super.onPostExecute(result);
        taskOver = true;
        positiveBtn.setEnabled(true);
        negativeBtn.setEnabled(false);
        if (result) {
            updateLog("AsyncTask ended. Download successfully");
        } else {
            updateLog("AsyncTask ended. Download failed");
        }
    }

    @Override
    protected void onCancelled() {
        super.onCancelled();
        taskOver = true;
        positiveBtn.setEnabled(true);
        negativeBtn.setEnabled(false);
        updateLog("AsyncTask cancelled");
    }
}
AsyncTask必须在UI线程中创建,

asyncTask.execute(Params... params) ;在UI线程中执行,且只能执行一次

要想再次调用execute(Params... params),必须重新创建AsyncTask对象


你可能感兴趣的:(AsyncTask的使用)