Android_AsyncTask详解及其应用(一)

来源:互联网 发布:一致性hash算法 编辑:程序博客网 时间:2024/05/19 19:30

之前介绍了Handler、Thread等知识,接下来就开始讲一下AsyncTask,他其实就是前两者封装而成,方便使用。有一点非常重要,使用AsyncTask一定要把API文档看清楚,为什么这么说,下文重点说到。

        AsyncTask 能够让你恰当容易地使用UI线程。AsyncTask其实是Android给开发者提供的一个简单轻量级的多线程类,通过它我们可以很容易新建一个线程做一些耗时的操作,并在这个过程中更新UI。之所以说它轻量级,是因为缺少了直接使用Thread的灵活性。这个类允许执行后台操作,在UI线程上发布的结果而无需操纵线程或Handler。AsyncTask设计出来的目的就是作为Thread和Handler的一个辅助类,并不构成一个通用线程框架。asynctasks应用于短作业(最多几秒钟)。如果你需要保持线程运行很长一段时间,那么强烈建议你使用javaAPIjava.util.concurrent包里面的类,例如Executor, ThreadPoolExecutor and FutureTask。一个AsyncTask任务由计算运行在后台线程上,其结果发表在UI线程上。它有三种参数类型, Params, Progress and Result和四个步骤:onPreExecute, doInBackground, onProgressUpdate and onPostExecute。

         AsyncTask必须使用子类,也就是必须继承  AsyncTask才能使用它。子类会覆盖至少一个方法(doInBackground(Params…)),通常将覆盖第二个(onPostExecute(Result))。
        下面看一个例子:

[java] view plaincopy
  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. }  
           一旦创建,执行一个任务非常简单:
[java] view plaincopy
  1. new DownloadFilesTask().execute(url1, url2, url3);  
           android的类AsyncTask对线程间通讯进行了包装,提供了简易的编程方式来使后台线程和UI线程进行通讯:后台线程执行异步任务,并把操作结果通知UI线程。
     AsyncTask是抽象类.AsyncTask定义了三种泛型类型 Params,Progress和Result。
     Params 启动任务执行的输入参数,比如HTTP请求的URL。
     Progress 后台任务执行的百分比。
     Result 后台执行任务最终返回的结果,比如String,Integer。

                                                                                       

              AsyncTask的执行分为四个步骤,每一步都对应一个回调方法,开发者需要实现这些方法。
                1) 继承AsyncTask
                2) 实现AsyncTask中定义的下面一个或几个方法
                     onPreExecute(), 该方法将在执行实际的后台操作前被UI 线程调用。可以在该方法中做一些准备工作,如在界面上显示一个进度条,或者一些控件的实例化,这个方法可以不用实现。
                    doInBackground(Params...), 将在onPreExecute 方法执行后马上执行,该方法运行在后台线程中。这里将主要负责执行那些很耗时的后台处理工作。可以调用 publishProgress方法来更新实时的任务进度。该方法是抽象方法,子类必须实现。
                    onProgressUpdate(Progress...),在publishProgress方法被调用后,UI 线程将调用这个方法从而在界面上展示任务的进展情况,例如通过一个进度条进行展示。
                    onPostExecute(Result), 在doInBackground 执行完成后,onPostExecute 方法将被UI 线程调用,后台的计算结果将通过该方法传递到UI 线程,并且在界面上展示给用户. 
                   onCancelled(),在用户取消线程操作的时候调用。在主线程中调用onCancelled()的时候调用。
           为了正确的使用AsyncTask类,以下是几条必须遵守的准则:
            1) Task的实例必须在UI 线程中创建
            2) execute方法必须在UI 线程中调用
            3) 不要手动的调用onPreExecute(), onPostExecute(Result),doInBackground(Params...), onProgressUpdate(Progress...)这几个方法,需要在UI线程中实例化这个task来调用。
           4) 该task只能被执行一次,否则多次调用时将会出现异常

                                                                    

                 doInBackground方法和onPostExecute的参数必须对应,这两个参数在AsyncTask声明的泛型参数列表中指定,第一个为doInBackground接受的参数,第二个为显示进度的参数,第第三个为doInBackground返回和onPostExecute传入的参数。阅读AsyncTask的源码可知,AsyncTask是使用java.util.concurrent 框架来管理线程以及任务的执行的。


实例

                 1、一个模拟下载进度条的例子

[java] view plaincopy
  1. package com.example.asynctaskdemo;  
  2.   
  3. import android.app.Activity;  
  4. import android.os.AsyncTask;  
  5. import android.os.Bundle;  
  6. import android.view.View;  
  7. import android.widget.Button;  
  8. import android.widget.ProgressBar;  
  9. import android.widget.TextView;  
  10.   
  11. public class Asy1Activity extends Activity {  
  12.   
  13.     Button download;  
  14.     ProgressBar pb;  
  15.     TextView tv;  
  16.   
  17.     /** Called when the activity is first created. */  
  18.     @Override  
  19.     public void onCreate(Bundle savedInstanceState) {  
  20.         super.onCreate(savedInstanceState);  
  21.         setContentView(R.layout.asy1);  
  22.         pb = (ProgressBar) findViewById(R.id.pb);  
  23.         tv = (TextView) findViewById(R.id.tv);  
  24.   
  25.         download = (Button) findViewById(R.id.download);  
  26.         download.setOnClickListener(new View.OnClickListener() {  
  27.             @Override  
  28.             public void onClick(View v) {  
  29.                 DownloadTask task=new DownloadTask();  
  30.                 task.execute(100);  
  31.             }  
  32.         });  
  33.     }  
  34.     class DownloadTask extends AsyncTask<Integer, Integer, String>{  
  35.   
  36.         @Override  
  37.         protected void onCancelled() {  
  38.             // TODO Auto-generated method stub  
  39.             super.onCancelled();  
  40.         }  
  41.   
  42.         @Override  
  43.         protected void onPostExecute(String result) {  
  44.             setTitle(result);   
  45.             super.onPostExecute(result);  
  46.         }  
  47.   
  48.         @Override  
  49.         protected void onPreExecute() {  
  50.             // TODO Auto-generated method stub  
  51.             super.onPreExecute();  
  52.         }  
  53.   
  54.         @Override  
  55.         protected void onProgressUpdate(Integer... values) {  
  56.             // TODO Auto-generated method stub  
  57.             super.onProgressUpdate(values);  
  58.             tv.setText(values[0]+"%");  
  59.               
  60.         }  
  61.   
  62.         @Override  
  63.         protected String doInBackground(Integer... params) {  
  64.             for(int i=0;i<=100;i++){  
  65.                 pb.setProgress(i);  
  66.                 publishProgress(i);    
  67.                  try {    
  68.                         Thread.sleep(params[0]);    
  69.                     } catch (InterruptedException e) {    
  70.                         e.printStackTrace();    
  71.                     }    
  72.             }  
  73.             return "执行完毕";  
  74.         }  
  75.           
  76.     }  
  77.       
  78. }  

                                                                                                   

         1、一个从网络下载图片的例子

[java] view plaincopy
  1. package com.example.asynctaskdemo;  
  2.   
  3. import java.io.ByteArrayOutputStream;  
  4. import java.io.IOException;  
  5. import java.io.InputStream;  
  6. import java.net.HttpURLConnection;  
  7. import java.net.MalformedURLException;  
  8. import java.net.URL;  
  9. import android.app.Activity;  
  10. import android.graphics.Bitmap;  
  11. import android.graphics.BitmapFactory;  
  12. import android.os.AsyncTask;  
  13. import android.os.Bundle;  
  14. import android.view.View;  
  15. import android.view.View.OnClickListener;  
  16. import android.widget.Button;  
  17. import android.widget.ImageView;  
  18. import android.widget.ProgressBar;  
  19.   
  20. public class Asy2Activity extends Activity {  
  21.   
  22.     private Button button;  
  23.     private ProgressBar progressBar;  
  24.     private ImageView imageView;  
  25.     private final String imageUrl = "http://avatar.csdn.net/D/1/4/1_wangjinyu501.jpg";  
  26.   
  27.     @Override  
  28.     protected void onCreate(Bundle savedInstanceState) {  
  29.         // TODO Auto-generated method stub  
  30.         super.onCreate(savedInstanceState);  
  31.         setContentView(R.layout.asy2);  
  32.         initView();  
  33.     }  
  34.   
  35.     private void initView() {  
  36.         button = (Button) findViewById(R.id.button);  
  37.         button.setOnClickListener(new OnClickListener() {  
  38.   
  39.             @Override  
  40.             public void onClick(View arg0) {  
  41.                 AsyncTaskLoadImage asyncTaskLoadImage = new AsyncTaskLoadImage();  
  42.   
  43.                 asyncTaskLoadImage.execute(imageUrl);  
  44.             }  
  45.         });  
  46.         progressBar = (ProgressBar) findViewById(R.id.pb);  
  47.         imageView = (ImageView) findViewById(R.id.imageview);  
  48.   
  49.     }  
  50.   
  51.     class AsyncTaskLoadImage extends AsyncTask<String, Integer, Bitmap> {  
  52.   
  53.         @Override  
  54.         protected void onPreExecute() {  
  55.             super.onPreExecute();  
  56.   
  57.         }  
  58.   
  59.         @Override  
  60.         protected Bitmap doInBackground(String... params) {  
  61.             Bitmap bitmap = null;  
  62.             try {  
  63.                 URL url = new URL(params[0]);  
  64.                 HttpURLConnection urlConnection = (HttpURLConnection) url  
  65.                         .openConnection();  
  66.                 urlConnection.connect();  
  67.                 int MAX = urlConnection.getContentLength();  
  68.                 progressBar.setMax(MAX);  
  69.   
  70.                 InputStream inputStream = urlConnection.getInputStream();  
  71.   
  72.                 ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();  
  73.                 byte[] b = new byte[1024];  
  74.                 int len = 0;  
  75.                 int processBarNum = 0;  
  76.                 while ((len = inputStream.read(b)) != -1) {  
  77.                     byteArrayOutputStream.write(b, 0, len);  
  78.                     processBarNum += len;  
  79.                     publishProgress(processBarNum);  
  80.                 }  
  81.                // bitmap = BitmapFactory.decodeStream(inputStream);  
  82.                 bitmap = BitmapFactory.decodeByteArray(  
  83.                         byteArrayOutputStream.toByteArray(), 0, MAX);  
  84.                 inputStream.close();  
  85.             } catch (MalformedURLException e) {  
  86.                 e.printStackTrace();  
  87.             } catch (IOException e) {  
  88.                 e.printStackTrace();  
  89.             }  
  90.             return bitmap;  
  91.         }  
  92.   
  93.         @Override  
  94.         protected void onProgressUpdate(Integer... values) {  
  95.             progressBar.setProgress(values[0]);  
  96.             super.onProgressUpdate(values);  
  97.   
  98.         }  
  99.   
  100.         @Override  
  101.         protected void onPostExecute(Bitmap result) {  
  102.   
  103.             imageView.setImageBitmap(result);  
  104.             super.onPostExecute(result);  
  105.         }  
  106.   
  107.     }  
  108.   
  109. }  

                                                                                                

原创粉丝点击