安卓開發筆記——關於AsyncTask的使用

在安卓開發中,咱們常常要進行一些耗時操做,好比數據庫操做,獲取網絡資源,讀取內存文件等等,當咱們在處理這些耗時操做的時候,若是咱們直接在UI主線程進行,那麼可能會致使阻塞UI主線程,使得UI界面卡頓,帶來很很差的用戶體驗,所以安卓也給咱們提供了2個異步操做的類,Handler和AsyncTask。java

今天先講AsyncTask,AsyncTask類是Andorid提供給咱們的一個輕量級異步類,算是一個框架,它對線程之間的通信進行了封裝,而且提供了簡易的編程操做,使得咱們能夠很輕鬆的實現後臺線程和UI主線程之間的通信。android

我寫了一個異步獲取網絡圖片的小例子,先來看實現效果:數據庫

 

以上是官網對AsyncTask的一些描述,大體意思是:apache

AsyncTask是一個易操做線程使用類,它能夠幫助咱們把後臺線程處理程序的結果發送給UI主線程,使UI線程獲得更新。編程

AsyncTask類提供了3個泛型參數(Params,Progress,Result)和4個執行步驟(下文會具體說起)數組

 

先來看下3個泛型參數網絡

一、Params:這是一個任務參數,通常咱們會定義成String類型的,例如本例子中要獲取網絡資源的URL地址app

二、Progress:任務執行的刻度,通常咱們會定義成Integer類型框架

三、Result:返回結果類型,例如本例中是對網絡圖片進行獲取,那麼它的返回類型應該是BitMap異步

 

再來看下4個步驟:

當咱們的類去實現AsyncTask類的時候至少須要實現doInBackground(Params...)方法,這裏做爲學習,我把每個的具體工做任務也說說

它的執行順序是這樣的 onPreExecute-->doInBackground-->onProgressUpdate-->onPostExecute

一、onPreExecute:這是一個預處理方法,在任務開始的時候執行,咱們能夠在這裏進行一些控件的實例化,設置屬性等。(非必須)

二、doInBackground:這是一個任務操做方法,也是最重要的一個方法,全部的耗時操做都應該在這裏執行。(必須)

三、onProgressUpdate:這是一個進度即時更新方法,在這裏咱們能夠即時更新任務滾動條的進度。(非必須,當在doInBackground裏調用publishProgress時觸發)

四、onPostExecute:這是一個任務結果處理方法,在doInBackground裏執行完任務,會將結果通知給這個類,在這類中咱們能夠對UI進行更新操做(非必須)

上面的一、三、4是UI主線程觸發調用的,因此能夠對UI進行更新操做,而第2步是個異步操做,不能在裏面進行UI的更新操做。

 

關於AsyncTask的調用,其實很是簡單,咱們在AsyncTask類被繼承實現的時候,在主線程直接對其對象調用execute(Params..)方法便可。

 

好了,文字介紹到此結束,上代碼:

一、佈局文件

 1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2     xmlns:tools="http://schemas.android.com/tools"
 3     android:layout_width="match_parent"
 4     android:layout_height="match_parent" 
 5     android:gravity="center"
 6     android:orientation="vertical">
 7 
 8     <ImageView
 9         android:id="@+id/imageView"
10         android:layout_width="wrap_content"
11         android:layout_height="wrap_content" />
12 
13     <Button
14         android:id="@+id/bt_download"
15         android:layout_width="wrap_content"
16         android:layout_height="wrap_content"
17         android:text="下載圖片" />
18 
19 </LinearLayout>

 

二、AsyncTask的實現類

  1 package com.example.asynctasktest;
  2 
  3 import java.io.ByteArrayOutputStream;
  4 import java.io.IOException;
  5 import java.io.InputStream;
  6 import java.io.OutputStream;
  7 
  8 import org.apache.http.HttpResponse;
  9 import org.apache.http.client.ClientProtocolException;
 10 import org.apache.http.client.HttpClient;
 11 import org.apache.http.client.methods.HttpGet;
 12 import org.apache.http.impl.client.DefaultHttpClient;
 13 
 14 import android.app.ProgressDialog;
 15 import android.graphics.Bitmap;
 16 import android.graphics.BitmapFactory;
 17 import android.os.AsyncTask;
 18 import android.widget.ImageView;
 19 
 20 public class MyAsyncTask extends AsyncTask<String, Integer, Bitmap> {
 21 
 22     private ImageView imageView;
 23     private ProgressDialog progressDialog;
 24 
 25     public MyAsyncTask(ImageView imageView, ProgressDialog progressDialog) {
 26         this.imageView = imageView;
 27         this.progressDialog = progressDialog;
 28     }
 29 
 30     /**
 31      * 執行第一步 這裏爲預處理操做,被UI線程所調用(能夠在這裏完成進度條的屬性設置)
 32      */
 33     @Override
 34     protected void onPreExecute() {
 35         super.onPreExecute();
 36         progressDialog.setTitle("當前任務");
 37         progressDialog.setMessage("正在下載圖片,請稍後...");
 38         progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);//設置進度條樣式,橫項
 39         progressDialog.show();
 40     }
 41 
 42     /**
 43      * 執行第二步 這裏爲異步線程,在這裏處理耗時任務操做(好比:下載,讀取文件)
 44      * 經過調用publishProgress方法(傳遞即時任務進度)能夠觸發onProgressUpdate的執行
 45      */
 46     @Override
 47     protected Bitmap doInBackground(String... params) {
 48         String path=params[0];
 49         Bitmap bitmap=null;
 50         HttpClient httpClient=new DefaultHttpClient();
 51         HttpGet httpGet=new HttpGet(path);
 52         InputStream inputStream=null;
 53         try {    
 54             HttpResponse httpResponse=httpClient.execute(httpGet);
 55             if(httpResponse.getStatusLine().getStatusCode()==200){
 56                 //鏈接成功
 57 //                HttpEntity entity=httpResponse.getEntity();
 58 //                byte[] data=EntityUtils.toByteArray(entity);
 59 //                bitmap=BitmapFactory.decodeByteArray(data, 0, data.length);
 60                 
 61                 inputStream=httpResponse.getEntity().getContent();
 62                 ByteArrayOutputStream outputStream=new ByteArrayOutputStream();
 63                 long fileSize=httpResponse.getEntity().getContentLength();//文件總大小
 64                 byte[] data=new byte[1024];//每次讀取的大小
 65                 int len=0;//本次讀取的大小
 66                 int total=0;//累計讀取的大小
 67                 while((len=inputStream.read(data))!=-1){
 68                         total+=len;//累計讀取的大小
 69                         int values=(int) ((total/(float)fileSize)*100);//獲得當前任務進行百分比
 70                         publishProgress(values);//觸發onProgressUpdate更新即時進度
 71                         outputStream.write(data, 0, len);
 72                 }
 73                 byte[] result=outputStream.toByteArray();//轉換爲字節數組
 74                 bitmap=BitmapFactory.decodeByteArray(result, 0, result.length);
 75             }
 76         } catch (ClientProtocolException e) {
 77             e.printStackTrace();
 78         } catch (IOException e) {
 79             e.printStackTrace();
 80         }finally{
 81             if(inputStream!=null){
 82                 try {
 83                     inputStream.close();
 84                 } catch (IOException e) {
 85                     e.printStackTrace();
 86                 }
 87             }
 88         }
 89         
 90         return bitmap;
 91 
 92     }
 93 
 94     /**
 95      * 執行第三步 這裏爲實時UI更新操做,被UI線程所調用 在這裏能夠即時更新(如進度條進度)
 96      */
 97     @Override
 98     protected void onProgressUpdate(Integer... values) {
 99         super.onProgressUpdate(values);
100         progressDialog.setProgress(values[0]);
101     }
102 
103     /**
104      * 執行第四步 在這裏會返回doInBackground的操做結果,被UI線程調用,更新最後UI結果
105      */
106     @Override
107     protected void onPostExecute(Bitmap result) {
108         super.onPostExecute(result);
109         progressDialog.dismiss();
110         imageView.setImageBitmap(result);
111     }
112 
113 }

 

三、主類

 1 package com.example.asynctasktest;
 2 
 3 import android.app.ProgressDialog;
 4 import android.os.Bundle;
 5 import android.support.v7.app.ActionBarActivity;
 6 import android.view.View;
 7 import android.view.View.OnClickListener;
 8 import android.widget.Button;
 9 import android.widget.ImageView;
10 
11 public class MainActivity extends ActionBarActivity {
12 
13     private ImageView imageView;
14     private Button bt_download;
15     private ProgressDialog progressDialog;//進度對話框
16     private String path="http://img.pconline.com.cn/images/photoblog/5/3/7/5/5375781/20096/6/1244302842840.jpg";//下載圖片路徑
17     
18     @Override
19     protected void onCreate(Bundle savedInstanceState) {
20         super.onCreate(savedInstanceState);
21         setContentView(R.layout.activity_main);
22         
23         imageView=(ImageView) findViewById(R.id.imageView);
24         bt_download=(Button) findViewById(R.id.bt_download);
25         progressDialog=new ProgressDialog(this);
26         
27         bt_download.setOnClickListener(new OnClickListener() {
28             
29             @Override
30             public void onClick(View v) {
31                 MyAsyncTask myAsyncTask=new MyAsyncTask(imageView,progressDialog);
32                 myAsyncTask.execute(path);
33             }
34         });
35         
36     }
37 
38 
39 }

 

代碼到此結束,註釋很詳細應該很好理解。

使用AsyncTask類,如下是幾條必須遵照的準則:

  • Task的實例必須在UI主線程中建立。
  • execute方法必須在UI主線程中調用。
  • 不要手動的調用onPreExecute(),onPostExecute(Result),doInBackground(Params...), onProgressUpdate(Progress...)這幾個方法。
  • 該task只能被執行一次,不然屢次調用時將會出現異常。

固然AsyncTask類不止這些東西,還有線程池的概念,今天先不講,過幾天連同Handler一塊兒說。

對於簡單的異步操做,掌握這些已經夠了。

 

項目代碼:http://pan.baidu.com/s/1kTkTgm7

 

做者:Balla_兔子
出處:http://www.cnblogs.com/lichenwei/本文版權歸做者和博客園共有,歡迎轉載,但未經做者贊成必須保留此段聲明,且在文章頁面明顯位置給出原文連接。正在看本人博客的這位童鞋,我看你氣度不凡,談吐間隱隱有王者之氣,往後必有一番做爲!旁邊有「推薦」二字,你就順手把它點了吧,相得準,我分文不收;相不許,你也好回來找我!

相關文章
相關標籤/搜索