您的位置:首页 > 其它

AsyncTask的使用

2016-03-16 15:28 531 查看
     参考: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定义了三个泛型数据Params,Progress和Result, 作用如下: 

           Params:启动task时传入的参数, 如new QAsyncTask().execute(Params), 这个输入参数是task执行过程中的调用函数doInBackground(Params)的输入参数

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

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

因此,一个最简单的自定义

AsyncTask
就可以写成如下方式:class DownloadTask extends AsyncTask<Void, Integer, Boolean> {……}
这里我们把

AsyncTask
的第一个泛型参数指定为
Void,表示在执行

AsyncTask
的时候不需要传入参数给后台任务。第二个泛型参数指定为

Integer,表示使用整型数据来作为进度显示单位。第三个泛型参数指定为

Boolean,则表示使用布尔型数据来反馈执行结果。

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), 可以同时运行5个task, 具体用法可以参考:

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

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



 

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



 

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



 
 重新执行第一步,期间不点击 Cancel 按钮



 

直至下载完成:



 

此时, 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对象
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: