Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發實例 >> Android應用開發入門(四十一)多線程之AsyncTask的使用

Android應用開發入門(四十一)多線程之AsyncTask的使用

編輯:Android開發實例

前言

  本文將介紹AsyncTask的使用,之前有介紹過線程和進程。而在AsyncTask中,運行在用戶界面中,執行異步操作,並且把執行結果發布在UI線程上,且也不需要處理線程和Handler。在本篇裡,將會講解到AsyncTask的基本介紹,以及如何使用,最後會以一個簡單的Demo講解AsyncTask的使用。

 

AsyncTask

  AsyncTask,異步任務,可以簡單進行異步操作,並把執行結果發布到UI主線程。AsyncTask是一個抽象類,它的內部其實也是結合了Thread和Handler來實現異步線程操作,但是它形成了一個通用線程框架,更清晰簡單。AsyncTask應該被用於比較簡短的操作(最多幾秒鐘)。如果需要保持長時間運行的線程,可以使用ThreadPooExecutor或者FutureTask,關於這兩個類的內容,以後再介紹,本片博客主要介紹AsyncTask。

  AsyncTask被定義為一個操作,運行在一個後台線程中,其結果被發布在UI線程上。它的異步工作的參數與返回值被泛型的三個參數指定:Params、Progress、Result。AsyncTask將經歷4個步驟:onPreExecute、doInBackground、onProgressUpdate、onPostExecute。下面詳細講解這三個參數與四個步驟:

  三個泛型參數:

  • Params:被發送到執行任務的參數類型。
  • Progress:進度的類型,發送後台的計算進度到UI線程類型。
  • Result:異步任務的返回結果類型。

  一個異步任務將經歷四個階段:

  • onPreExecute():執行在UI線程上調用執行任務之前,一般用於設置任務。
  • doInBackground(Params...):主要是用來執行異步任務的耗時操作,可以在這個方法中通過publishProgress()方法發布進度信息,並在執行完成之後,返回執行結果。
  • onProgreddUpdate(Progress...):在UI線程上接受doInBackground()傳遞過來的進度信息,並在UI線程上展示進度信息,它執行的時機是不確定的。
  • onPostExecute(Result):在UI線程上操作doInBackground()執行的返回值。

  上面介紹的四個步驟的示意圖:

 

AsyncTask取消任務

  在程序的任何位置,都可以通過cancel(boolean)方法進行取消任務,當取消任務之後,會改變isCancelled()的返回值,使其返回true。之後會調用onCancelled(Object)方法,替代onPostExecute()得到doInBackground()的返回結果。在運行中,可以經常通過isCancelled()方法查看任務是否被取消。

 

AsyncTask的使用規則

  使用AsyncTask必須遵循以下規則:

  • AsyncTask必須聲明在UI線程上。
  • AsyncTask必須在UI線程上實例化。
  • 必須通過execute()方法執行任務。
  • 不可以直接調用onPreExecute()、onPostExecute(Resut)、doInBackground(Params...)、onProgressUpdate(Progress...)方法。
  • 可以設置任務只執行一次,如果企圖再次執行會報錯。

示例

  一個簡單的示例,通過AsyncTask下載一個網絡上的圖片,下載的時候展示一個等待框,並顯示在一個ImageView中。

  實現代碼:

  1. package com.bgxt.datatimepickerdemo;  
  2.  
  3. import org.apache.http.HttpEntity;  
  4. import org.apache.http.HttpResponse;  
  5. import org.apache.http.client.HttpClient;  
  6. import org.apache.http.client.methods.HttpGet;  
  7. import org.apache.http.impl.client.DefaultHttpClient;  
  8. import org.apache.http.util.EntityUtils;  
  9.  
  10. import android.app.Activity;  
  11. import android.app.ProgressDialog;  
  12. import android.graphics.Bitmap;  
  13. import android.graphics.BitmapFactory;  
  14. import android.os.AsyncTask;  
  15. import android.os.Bundle;  
  16. import android.view.View;  
  17. import android.widget.Button;  
  18. import android.widget.ImageView;  
  19.  
  20. public class AsyncTaskActivity1 extends Activity {  
  21.     private Button btnDown;  
  22.     private ImageView ivImage;  
  23.     private static String image_path = "http://ww4.sinaimg.cn/bmiddle/786013a5jw1e7akotp4bcj20c80i3aao.jpg";  
  24.     private ProgressDialog dialog;  
  25.  
  26.     @Override 
  27.     protected void onCreate(Bundle savedInstanceState) {  
  28.         // TODO Auto-generated method stub  
  29.         super.onCreate(savedInstanceState);  
  30.         setContentView(R.layout.asynctask_activity);  
  31.  
  32.         btnDown = (Button) findViewById(R.id.btnDown);  
  33.         ivImage = (ImageView) findViewById(R.id.ivSinaImage);  
  34.           
  35.         // 聲明一個等待框以提示用戶等待  
  36.         dialog=new ProgressDialog(this);  
  37.         dialog.setTitle("提示信息");  
  38.         dialog.setMessage("正在下載,請稍後...");  
  39.           
  40.         btnDown.setOnClickListener(new View.OnClickListener() {  
  41.  
  42.             @Override 
  43.             public void onClick(View v) {  
  44.                 // 執行一個異步任務,並把圖片地址以參數的形式傳遞進去  
  45.                 new MyTask().execute(image_path);  
  46.             }  
  47.         });  
  48.     }  
  49.  
  50.     // 以String類型的參數,Void表示沒有進度信息,Bitmap表示異步任務返回一個位圖  
  51.     public class MyTask extends AsyncTask<String, Void, Bitmap> {  
  52.         // 表示任務執行之前的操作  
  53.         @Override 
  54.         protected void onPreExecute() {  
  55.             super.onPreExecute();  
  56.             //顯示等待框  
  57.             dialog.show();  
  58.         }  
  59.  
  60.         //主要是完成耗時操作  
  61.         @Override 
  62.         protected Bitmap doInBackground(String... params) {  
  63.             HttpClient httpClient=new DefaultHttpClient();  
  64.             HttpGet httpGet=new HttpGet(params[0]);  
  65.             Bitmap bitmap=null;  
  66.             try {  
  67.                 //從網絡上下載圖片  
  68.                 HttpResponse httpResponse =httpClient.execute(httpGet);  
  69.                 if(httpResponse.getStatusLine().getStatusCode()==200){  
  70.                     HttpEntity httpEntity = httpResponse.getEntity();  
  71.                     byte[] data=EntityUtils.toByteArray(httpEntity);  
  72.                     bitmap=BitmapFactory.decodeByteArray(data, 0, data.length);                      
  73.                 }  
  74.             } catch (Exception e) {  
  75.                 e.printStackTrace();  
  76.             }  
  77.             return bitmap;  
  78.         }  
  79.           
  80.         //完成更新UI操作  
  81.         @Override 
  82.         protected void onPostExecute(Bitmap result) {  
  83.             // TODO Auto-generated method stub  
  84.             super.onPostExecute(result);  
  85.             //設置ImageView的顯示圖片  
  86.             ivImage.setImageBitmap(result);  
  87.             // 銷毀等待框  
  88.             dialog.dismiss();  
  89.         }  
  90.  
  91.     }  

 效果展示:

  上面的Demo並沒有用到進度的信息,下面在提供一個完整的AsyncTask的Demo,同樣是下載一個圖片,並且展示到一個ImageView中,但是這裡在下載的過程中增加一個進度條對話框,用於展示下載的進度。

  實現代碼:

 

  1. package com.bgxt.datatimepickerdemo;  
  2.  
  3. import java.io.ByteArrayOutputStream;  
  4. import java.io.InputStream;  
  5.  
  6. import org.apache.http.HttpResponse;  
  7. import org.apache.http.client.HttpClient;  
  8. import org.apache.http.client.methods.HttpGet;  
  9. import org.apache.http.impl.client.DefaultHttpClient;  
  10.  
  11. import android.app.Activity;  
  12. import android.app.ProgressDialog;  
  13. import android.graphics.Bitmap;  
  14. import android.graphics.BitmapFactory;  
  15. import android.os.AsyncTask;  
  16. import android.os.Bundle;  
  17. import android.view.View;  
  18. import android.widget.Button;  
  19. import android.widget.ImageView;  
  20.  
  21. public class AsyncTaskActivity2 extends Activity {  
  22.     private Button btnDown;  
  23.     private ImageView ivImage;  
  24.     private static String image_path = "http://ww4.sinaimg.cn/bmiddle/786013a5jw1e7akotp4bcj20c80i3aao.jpg";  
  25.     private ProgressDialog dialog;  
  26.  
  27.     @Override 
  28.     protected void onCreate(Bundle savedInstanceState) {  
  29.         super.onCreate(savedInstanceState);  
  30.         setContentView(R.layout.asynctask_activity);  
  31.         btnDown = (Button) findViewById(R.id.btnDown);  
  32.         ivImage = (ImageView) findViewById(R.id.ivSinaImage);  
  33.  
  34.         dialog = new ProgressDialog(this);  
  35.         dialog.setTitle("提示");  
  36.         dialog.setMessage("正在下載,請稍後...");  
  37.         dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);  
  38.         dialog.setCancelable(false);  
  39.  
  40.         btnDown.setOnClickListener(new View.OnClickListener() {  
  41.  
  42.             @Override 
  43.             public void onClick(View v) {  
  44.                 //  執行異步任務  
  45.                 new MyTask().execute(image_path);  
  46.             }  
  47.         });  
  48.     }  
  49.  
  50.     public class MyTask extends AsyncTask<String, Integer, Bitmap> {  
  51.         @Override 
  52.         protected void onPreExecute() {  
  53.             super.onPreExecute();  
  54.             dialog.show();  
  55.         }  
  56.  
  57.         @Override 
  58.         protected void onProgressUpdate(Integer... values) {  
  59.             super.onProgressUpdate(values);  
  60.             // 設置進度對話框的進度值  
  61.             dialog.setProgress(values[0]);  
  62.         }  
  63.  
  64.         @Override 
  65.         protected void onPostExecute(Bitmap result) {  
  66.             super.onPostExecute(result);  
  67.             dialog.dismiss();  
  68.             ivImage.setImageBitmap(result);  
  69.         }  
  70.  
  71.         @Override 
  72.         protected Bitmap doInBackground(String... params) {  
  73.             Bitmap bitmap = null;  
  74.             ByteArrayOutputStream outputStream = new ByteArrayOutputStream();  
  75.             InputStream inputStream = null;  
  76.             try {  
  77.                 HttpClient httpClient = new DefaultHttpClient();  
  78.                 HttpGet httpGet = new HttpGet(params[0]);  
  79.                 HttpResponse httpResponse = httpClient.execute(httpGet);  
  80.                 if (httpResponse.getStatusLine().getStatusCode() == 200) {  
  81.                     inputStream = httpResponse.getEntity().getContent();  
  82.                     long file_length = httpResponse.getEntity()  
  83.                             .getContentLength();  
  84.                     int len = 0;  
  85.                     byte[] data = new byte[1024];  
  86.                     int total_length = 0;  
  87.                     // 以字節的方式讀取圖片數據  
  88.                     while ((len = inputStream.read(data)) != -1) {  
  89.                         total_length += len;  
  90.                         // 計算進度  
  91.                         int values = (int) ((total_length / (float) file_length) * 100);  
  92.                         // 發布進度信息  
  93.                         publishProgress(values);  
  94.                         outputStream.write(data, 0, len);  
  95.                     }  
  96.                     byte[] result=outputStream.toByteArray();  
  97.                     bitmap=BitmapFactory.decodeByteArray(result, 0, result.length);  
  98.                 }  
  99.             } catch (Exception e) {  
  100.                 e.printStackTrace();  
  101.             } finally {  
  102.                 try {  
  103.                     if (inputStream != null) {  
  104.                         inputStream.close();  
  105.                     }  
  106.                 } catch (Exception e2) {  
  107.                 }  
  108.             }  
  109.             return bitmap;  
  110.         }  
  111.     }  

 實現效果:

  源碼下載

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved