【Android】AsyncTask

AsyncTask enables proper and easy use of the UI thread. This class allows to perform background operations and publish results on the UI thread without having to manipulate threads and/or handlers.(这个类允许在后台运行线程并且将运行结果反映到UI线程)

AsyncTask is designed to be a helper class around Thread and Handler and does not constitute a generic threading framework. AsyncTasks should ideally be used for short operations (a few seconds at the most.) If you need to keep threads running for long periods of time, it is highly recommended you use the various APIs provided by the java.util.concurrent pacakge such as ExecutorThreadPoolExecutor and FutureTask.(AsyncTask被设计成Thread和Handler的帮助类,AsyncTask应当被用来执行短任务(最多几秒:加载图片不是很好么),如果保保持线程长时间运行,最好使用其他的线程类)

An asynchronous task is defined by a computation that runs on a background thread and whose result is published on the UI thread. An asynchronous task is defined by 3 generic types, called ParamsProgress and Result, and 4 steps, called onPreExecutedoInBackgroundonProgressUpdate andonPostExecute.(任务的定义由三部分组成,完成由四部分组成)

Developer Guides

For more information about using tasks and threads, read the Processes and Threads developer guide.

Usage

AsyncTask must be subclassed to be used. The subclass will override at least one method (doInBackground(Params...)), and most often will override a second one (onPostExecute(Result).)(AsyncTask必须被继承!!)

Here is an example of subclassing:

 

 1 private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
 2      protected Long doInBackground(URL... urls) {
 3          int count = urls.length;
 4          long totalSize = 0;
 5          for (int i = 0; i < count; i++) {
 6              totalSize += Downloader.downloadFile(urls[i]);
 7              publishProgress((int) ((i / (float) count) * 100));
 8              // Escape early if cancel() is called
 9              if (isCancelled()) break;
10          }
11          return totalSize;
12      }
13 
14      protected void onProgressUpdate(Integer... progress) {
15          setProgressPercent(progress[0]);
16      }
17 
18      protected void onPostExecute(Long result) {
19          showDialog("Downloaded " + result + " bytes");
20      }
21  }

Once created, a task is executed very simply:

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

AsyncTask's generic types

The three types used by an asynchronous task are the following:

  1. Params, the type of the parameters sent to the task upon execution.
  2. Progress, the type of the progress units published during the background computation.
  3. Result, the type of the result of the background computation.

Not all types are always used by an asynchronous task. To mark a type as unused, simply use the type Void:

private class MyTask extends AsyncTask<Void, Void, Void> { ... }

The 4 steps

When an asynchronous task is executed, the task goes through 4 steps:(当一个异步任务被执行,这个任务要经过四步)

1)onPreExecute(), invoked on the UI thread immediately after the task is executed. This step is normally used to setup the task, for instance by showing a progress bar in the user interface.(UI线程在启动任务后立即调用)

2)doInBackground(Params...), invoked on the background thread immediately after onPreExecute() finishes executing. This step is used to perform background computation that can take a long time. The parameters of the asynchronous task are passed to this step. The result of the computation must be returned by this step and will be passed back to the last step. This step can also use publishProgress(Progress...) to publish one or more units of progress. These values are published on the UI thread, in the onProgressUpdate(Progress...) step.(前一个方法完成之后由后台进程调用,这一步是运行耗时的后台计算的,异步任务的参数就是被传递到这个函数的,计算的结果必须被返回给下一步,这一步也可以使用publishProgress来展现更细节的过程,这些值被展现在UI线程上面)

3)onProgressUpdate(Progress...), invoked on the UI thread after a call to publishProgress(Progress...). The timing of the execution is undefined. This method is used to display any form of progress in the user interface while the background computation is still executing. For instance, it can be used to animate a progress bar or show logs in a text field.(当UI线程调用publishProgress方法后用来展现任务的进度的,可以向外暴露一些进程信息)

4)onPostExecute(Result), invoked on the UI thread after the background computation finishes. The result of the background computation is passed to this step as a parameter.(结果被传递到这里,计算完成后结束)

大致看一下代码(比较好理解,来自博客:Android中AsyncTask的用法实例

 1  // 设置三种类型参数分别为String,Integer,String  
 2      class PageTask extends AsyncTask<String, Integer, String> 3    
 4          // 可变长的输入参数,与AsyncTask.exucute()对应  
 5          @Override  
 6          protected String doInBackground(String... params) {  
 7              try 8                  HttpClient client = new DefaultHttpClient();  
 9                  // params[0] 代表连接的url  
10                  HttpGet get = new HttpGet(params[0]);  
11                  HttpResponse response = client.execute(get);  
12                  HttpEntity entity = response.getEntity();  
13                  long length = entity.getContentLength(); //获取长度 
14                  InputStream is = entity.getContent();  
15                  String s = null16                  if (is != null) {  
17                      ByteArrayOutputStream baos = new ByteArrayOutputStream();  
18                      byte[] buf = new byte[128];  
19                      int ch = -120                      int count = 021                      while ((ch = is.read(buf)) != -1) {  
22                          baos.write(buf, 0, ch);  
23                          count += ch;  
24                          if (length > 0) {  
25                              // 如果知道响应的长度,调用publishProgress()更新进度  
26                              publishProgress((int) ((count / (float) length) * 100));  //调用这个方法展现任务进度
27                          }  
28                          // 为了在模拟器中清楚地看到进度,让线程休眠100ms  
29                          Thread.sleep(100);  
30                      }  
31                      s = new String(baos.toByteArray());             }  
32                  // 返回结果  
33                  return s;  
34              } catch (Exception e) {  
35                  e.printStackTrace();  
36              }  
37              return null38          }  
39          @Override  
40          protected void onCancelled() {  
41              super.onCancelled();  
42          }  
43          @Override  
44          protected void onPostExecute(String result) {  
45              // 返回HTML页面的内容  
46              message.setText(result);  //最后执行
47          }  
48          @Override  
49          protected void onPreExecute() {  
50              // 任务启动,可以在这里显示一个对话框,这里简单处理  
51              message.setText(R.string.task_started);  //最前面执行
52          }  
53          @Override  
54          protected void onProgressUpdate(Integer... values) {  
55              // 更新进度  
56              message.setText(values[0]);  //进度更新
57          }  
58      }

调用这个类的方法很简单:

1 PageTask task = new PageTask();  
2 task.execute(url.getText().toString());

Cancelling a task

A task can be cancelled at any time by invoking cancel(boolean). Invoking this method will cause subsequent calls to isCancelled() to return true. After invoking this method, onCancelled(Object), instead of onPostExecute(Object) will be invoked after doInBackground(Object[]) returns. To ensure that a task is cancelled as quickly as possible, you should always check the return value of isCancelled() periodically fromdoInBackground(Object[]), if possible (inside a loop for instance.)(可以随时终止一个任务,种植之后isCancelled方法就会返回true,之后,doInBackground完成之后将调用onCancelled方法额不是onPostExecute方法,为了保证任务能够及时取消,应该在doInBackground里面一直检测isCancelled的返回值)

Threading rules

There are a few threading rules that must be followed for this class to work properly:

Memory observability(线程同步)

AsyncTask guarantees that all callback calls are synchronized in such a way that the following operations are safe without explicit synchronizations.

Order of execution

When first introduced, AsyncTasks were executed serially on a single background thread. Starting with DONUT, this was changed to a pool of threads allowing multiple tasks to operate in parallel. Starting with HONEYCOMB, tasks are executed on a single thread to avoid common application errors caused by parallel execution.

If you truly want parallel execution, you can invoke executeOnExecutor(java.util.concurrent.Executor, Object[]) withTHREAD_POOL_EXECUTOR.

posted @ 2012-10-23 17:52  大脚印  阅读(515)  评论(0编辑  收藏  举报