AsyncTask异步任务

来源:互联网 发布:php cgi 性能 编辑:程序博客网 时间:2024/06/04 19:41

AsyncTask介绍

Android的AsyncTask比Handler更轻量级一些,适用于简单的异步处理。
首先明确Android之所以有Handler和AsyncTask,都是为了不阻塞主线程(UI线程),且UI的更新只能在主线程中完成,因此异步处理是不可避免的。

Android为了降低这个开发难度,提供了AsyncTask。AsyncTask就是一个封装过的后台任务类,顾名思义就是异步任务。

AsyncTask直接继承于Object类,位置为android.os.AsyncTask。要使用AsyncTask工作我们要提供三个泛型参数,并重载几个方法(至少重载一个)。

AsyncTask定义了三种泛型类型 Params,Progress和Result。

Params 启动任务执行的输入参数,比如HTTP请求的URL。
Progress 后台任务执行的百分比。
Result 后台执行任务最终返回的结果,比如String。
使用过AsyncTask 的同学都知道一个异步加载数据最少要重写以下这两个方法:

doInBackground(Params…) 后台执行,比较耗时的操作都可以放在这里。注意这里不能直接操作UI。此方法在后台线程执行,完成任务的主要工作,通常需要较长的时间。在执行过程中可以调用publicProgress(Progress…)来更新任务的进度。
onPostExecute(Result) 相当于Handler 处理UI的方式,在这里面可以使用在doInBackground 得到的结果处理操作UI。 此方法在主线程执行,任务执行的结果作为此方法的参数返回
有必要的话你还得重写以下这三个方法,但不是必须的:

onProgressUpdate(Progress…) 可以使用进度条增加用户体验度。 此方法在主线程执行,用于显示任务执行的进度。
onPreExecute() 这里是最终用户调用Excute时的接口,当任务执行之前开始调用此方法,可以在这里显示进度对话框。
onCancelled() 用户调用取消时,要做的操作
使用AsyncTask类,以下是几条必须遵守的准则:

Task的实例必须在UI thread中创建;
execute方法必须在UI thread中调用;
不要手动的调用onPreExecute(), onPostExecute(Result),doInBackground(Params…), onProgressUpdate(Progress…)这几个方法;
该task只能被执行一次,否则多次调用时将会出现异常;

AsyncTask必须被子类继承来使用。
这里有一个简单子类的例子:

private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {     protected Long doInBackground(URL... urls) {         int count = urls.length;         long totalSize = 0;         for (int i = 0; i < count; i++) {             totalSize += Downloader.downloadFile(urls[i]);             publishProgress((int) ((i / (float) count) * 100));             // Escape early if cancel() is called             if (isCancelled()) break;         }         return totalSize;//此结果会传递给onPostExecute()     }     protected void onProgressUpdate(Integer... progress) {         setProgressPercent(progress[0]);//这里在UI显示状态条     }     protected void onPostExecute(Long result) {         showDialog("Downloaded " + result + " bytes");     } }

想执行这个任务的话:

 new DownloadFilesTask().execute(url1, url2, url3);

使用

当一个异步任务执行,会有4步:
1.onPreExecute(),任务被执行之前在UI线程引用该函数。该方法一般用于setup任务,比如在用户界面显示进度条。
2.doInBackground(Params…), 在onPreExecute()执行完毕之后立即在后台线程中调用该方法。此方法用于执行后台的耗时计算。异步任务的参数会传递到这个方法中,此方法的计算结果必须返回给最后一步,此方法中也可以调用publishProgress(Progress…)来公布一个或多个任务百分比。这些值会在onProgressUpdate(Progress…)方法、UI中发布。
3.onProgressUpdate(Progress…),在调用publishProgress(Progress…)后会在UI线程中引用。执行时间没有定义。该方法会在后台计算继续执行的过程中在用户界面显示任何形式的进度。比如,它可以被调用来创建一个进度条或在text中显示logs。
4.onPostExecute(Result), 在后台计算完毕后会在UI线程引用该方法,后台计算的结果会被传递给这个方法。

取消任务

任务可以通过调用cancel(boolean)在任何时候取消任务。调用此方法将会使isCancelled()返回true。调用该方法后,在doInBackground(Object)返回后,执行onCancelled(Object[]),而不是onpostExecute(Object)。为了确保任务能尽快取消,我们应该尽可能的在doInBackground(Object[])中检查isCancelled()的值。

执行规则:

第一次声明的时候AsyncTask被顺序执行在一个单后台线程中。
以DONUT开始,则变为一些线程,此时允许多任务并行执行。
以HONEYCOMB开始,任务在单线程执行,避免因并行导致的common application errors。

如果需要并行执行,可以引用executeOnExecutor(java.util.concurrent.Executor, Object[]) with THREAD_POOL_EXECUTOR.

0 0
原创粉丝点击