Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android技術基礎 >> 第82章、異步處理工具類:AsyncTask(從零開始學Android)

第82章、異步處理工具類:AsyncTask(從零開始學Android)

編輯:Android技術基礎

(一)  AsyncTask,是android提供的輕量級的異步類。可以直接繼承AsyncTask,在類中實現異步操作,可以通過接口實現UI進度更新,最後反饋執行的結果給UI主線程

。之所以有Handler和AsyncTask,都是為了不阻塞主線程(UI線程),且UI的更新只能在主線程中完成,因此異步處理是不可避免的。

AsyncTask直接繼承於Object類,位置為android.os.AsyncTask。要使用AsyncTask工作我們要提供三個泛型參數,並重載幾個方法(至少重載一個)。

1、AsyncTask定義了三種泛型類型 Params,Progress和Result。
(1)Params 啟動任務執行的輸入參數,比如HTTP請求的URL。
(2)Progress 後台任務執行的百分比。
(3)Result 後台執行任務最終返回的結果,比如String。

2、使用過AsyncTask 最少要重寫以下這兩個方法:
(1)doInBackground(Params…) 後台執行,比較耗時的操作都可以放在這裡。注意這裡不能直接操作UI。此方法在後台線程執行,完成任務的主要工作,通常需要較長的時間。在執行過程中可以調用publicProgress(Progress…)來更新任務的進度。

(2)onPostExecute(Result) 相當於Handler 處理UI的方式,在這裡面可以使用在doInBackground 得到的結果處理操作UI。 此方法在主線程執行,任務執行的結果作為此方法的參數返回

另外三個方法可選,不是必須的:

(3)onProgressUpdate(Progress…) 可以使用進度條增加用戶體驗度。 此方法在主線程執行,用於顯示任務執行的進度。
(4)onPreExecute() 這裡是最終用戶調用Excute時的接口,當任務執行之前開始調用此方法,可以在這裡顯示進度對話框。
(5)onCancelled() 用戶調用取消時,要做的操作

3、使用AsyncTask類,以下是幾條必須遵守的准則:
(1)Task的實例必須在UI thread中創建;
(2)execute方法必須在UI thread中調用;
(3)不要手動的調用onPreExecute(), onPostExecute(Result),doInBackground(Params...), onProgressUpdate(Progress...)這幾個方法;
(4)該task只能被執行一次,否則多次調用時將會出現異常;

(二)AsyncTask和Handler對比

1、AsyncTask實現的原理,和適用的優缺點

AsyncTask,是android提供的輕量級的異步類,可以直接繼承AsyncTask,在類中實現異步操作,並提供接口反饋當前異步執行的程度(可以通過接口實現UI進度更新),最後反饋執行的結果給UI主線程.

(1)使用的優點:

A、簡單,快捷;
B、過程可控。

(2)使用的缺點:

在使用多個異步操作和並需要進行Ui變更時,就變得復雜起來。

2、Handler異步實現的原理和適用的優缺點

在Handler 異步實現時,涉及到Handler、Looper、Message、Thread四個對象,實現異步的流程是主線程啟動Thread(子線程)àthread(子線程)運行並生成Message-Looper獲取Message並傳遞給HandleràHandler逐個獲取Looper中的Message,並進行UI變更。

(1)使用的優點:

A、 結構清晰,功能定義明確

B、 對於多個後台任務時,簡單,清晰

 

(2)使用的缺點:

在單個後台異步處理時,顯得代碼過多,結構過於復雜(相對性)

 

一、設計界面

1、布局文件

打開res/layout/activity_main.xml文件。
輸入以下代碼:

[html] view plain copy  
  1. <LinearLayout   
  2.     xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent"  
  5.     android:orientation="vertical" >  
  6.     <EditText  
  7.         android:id="@+id/url"  
  8.         android:layout_width="wrap_content"  
  9.         android:layout_height="wrap_content"  
  10.         android:layout_alignParentLeft="true" >  
  11.         <requestFocus />  
  12.     </EditText>  
  13.   
  14.     <Button  
  15.         android:id="@+id/open"  
  16.         android:layout_width="wrap_content"  
  17.         android:layout_height="wrap_content"  
  18.         android:layout_alignParentLeft="true"  
  19.         android:text="AsyncTask處理" />  
  20.   
  21.     <EditText  
  22.         android:id="@+id/message"  
  23.         android:layout_width="match_parent"  
  24.         android:layout_height="wrap_content"  
  25.         android:inputType="textMultiLine" />  
  26.   
  27. </LinearLayout>  

 

二、程序文件

打開“src/com.genwoxue.contentprovider_b/MainActivity.java”文件。
然後輸入以下代碼:

[java] view plain copy  
  1. package com.genwoxue.asynctask;  
  2.   
  3. import java.io.ByteArrayOutputStream;    
  4. import java.io.InputStream;    
  5. import org.apache.http.HttpEntity;    
  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. import android.app.Activity;    
  11. import android.app.ProgressDialog;    
  12. import android.content.Context;    
  13. import android.content.DialogInterface;    
  14. import android.os.AsyncTask;    
  15. import android.os.Bundle;    
  16. import android.view.View;    
  17. import android.widget.Button;    
  18. import android.widget.EditText;    
  19. import android.widget.TextView;     
  20.   
  21. public class MainActivity extends Activity{     
  22.     private EditText message;        
  23.     private Button open;        
  24.     private EditText url;        
  25.       
  26.     @Override       
  27.     public void onCreate(Bundle savedInstanceState) {           
  28.         super.onCreate(savedInstanceState);           
  29.         setContentView(R.layout.activity_main);           
  30.         message= (EditText) findViewById(R.id.message);           
  31.         url= (EditText) findViewById(R.id.url);         
  32.         url.setText("http://www.genwoxue.com");  
  33.         open= (Button) findViewById(R.id.open);           
  34.         open.setOnClickListener(new View.OnClickListener() {               
  35.             public void onClick(View arg0) {                
  36.                 connect();           
  37.                 }         
  38.             });         
  39.         }       
  40.     private void connect() {     
  41.         PageTask task = new PageTask(this);        
  42.         task.execute(url.getText().toString());      
  43.     }        
  44.       
  45.     /* 四個步驟: 
  46.      * (1)onPreExecute(),執行預處理,它運行於UI線程, 
  47.      * 可以為後台任務做一些准備工作,比如繪制一個進度條控件。 
  48.      * (2)doInBackground(Params...),後台進程執行的具體計算在這裡實現, 
  49.      * doInBackground(Params...)是AsyncTask的關鍵,此方法必須重載。 
  50.      * 在這個方法內可以使用 publishProgress(Progress...)改變當前的進度值。 
  51.      * (3)onProgressUpdate(Progress...),運行於UI線程。如果 
  52.      * 在doInBackground(Params...) 中使用了publishProgress(Progress...),就會 
  53.      * 觸發這個方法。在這裡可以對進度條控件根據進度值做出具體的響應。 
  54.      * (4)onPostExecute(Result),運行於UI線程,可以對後台任務的結果做出處理,結果 
  55.      * 就是doInBackground(Params...)的返回值。此方法也要經常重載,如果Result為 
  56.      * null表明後台任務沒有完成(被取消或者出現異常)。    *  
  57.      */  
  58.     class PageTask extends AsyncTask<String, Integer, String> {      
  59.         // 可變長的輸入參數,與AsyncTask.exucute()對應      
  60.         ProgressDialog pdialog;      
  61.         public PageTask(Context context){      
  62.             pdialog = new ProgressDialog(context, 0);     
  63.             pdialog.setButton("cancel", new DialogInterface.OnClickListener() {   
  64.                 public void onClick(DialogInterface dialog, int i) {      
  65.                     dialog.cancel();          
  66.                 }            
  67.             });            
  68.               
  69.         pdialog.setOnCancelListener(new DialogInterface.OnCancelListener() {       
  70.                 public void onCancel(DialogInterface dialog) {             
  71.                     finish();             
  72.                 }            
  73.         });            
  74.           
  75.         pdialog.setCancelable(true);     
  76.         pdialog.setMax(100);           
  77.         pdialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);       
  78.         pdialog.show();             
  79.     }      
  80.           
  81.         // (1)任務啟動  
  82.         @Override          
  83.         protected void onPreExecute() {       
  84.             message.setText("task_started");          
  85.         }    
  86.           
  87.         //(2)後台執行:主要工作在這裡實現  
  88.         @Override            
  89.         protected String doInBackground(String... params) {     
  90.             String result = null;  
  91.             try{                 
  92.                 HttpClient client = new DefaultHttpClient();         
  93.                 HttpGet get = new HttpGet(params[0]);       // params[0]代表連接的url        
  94.                 HttpResponse response = client.execute(get);          
  95.                 HttpEntity entity = response.getEntity();              
  96.                 long length = entity.getContentLength();                
  97.                 InputStream is = entity.getContent();                  
  98.                 if(is != null) {                       
  99.                     ByteArrayOutputStream baos = new ByteArrayOutputStream();            
  100.                     byte[] buf = new byte[128];                    
  101.                     int ch = -1;                     
  102.                     int count = 0;                    
  103.                     while((ch = is.read(buf)) != -1) {          
  104.                         baos.write(buf, 0, ch);     
  105.                           
  106.                         count += ch;                          
  107.                         if(length > 0) {                             
  108.                             // 如果知道響應的長度,調用publishProgress()更新進度            
  109.                             publishProgress((int) ((count / (float) length) * 100));                  
  110.                             }                           
  111.                             Thread.sleep(50);    // 讓線程休眠50ms                  
  112.                         }            
  113.                     result = new String(baos.toByteArray());            
  114.                 }                
  115.                     return result;     // 返回結果              
  116.             } catch(Exception e) {           
  117.                 e.printStackTrace();          
  118.             }               
  119.             return null;        
  120.         }            
  121.           
  122.           
  123.         //(3)由doInBackground中的publishProgress(Progress...)觸發onProgressUpdate這個方法  
  124.         @Override         
  125.         protected void onProgressUpdate(Integer... values) {        
  126.             // 更新進度              
  127.             System.out.println(""+values[0]);     
  128.             message.setText(""+values[0]);      
  129.             pdialog.setProgress(values[0]);        
  130.         }        
  131.                   
  132.         //(4)可以對後台任務的結果做出處理,結果就是doInBackground(Params...)的返回值。  
  133.         @Override       
  134.         protected void onPostExecute(String result) {      
  135.             // 返回HTML頁面的內容                
  136.             message.setText(result);         
  137.             pdialog.dismiss();           
  138.         }    
  139.           
  140.         @Override            
  141.         protected void onCancelled() {       
  142.             super.onCancelled();          
  143.         }      
  144.           
  145.     }     
  146. }  

 

三、配置文件

打開“AndroidManifest.xml”文件。

然後輸入以下代碼:

[html] view plain copy  
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     package="com.genwoxue.asynctask"  
  4.     android:versionCode="1"  
  5.     android:versionName="1.0" >  
  6.   
  7.     <uses-sdk  
  8.         android:minSdkVersion="10"  
  9.         android:targetSdkVersion="15" />  
  10.       
  11.     <span style="color:#ff0000;"><strong><uses-permission android:name="android.permission.INTERNET"/></strong>  
  12. </span>  
  13.     <application  
  14.         android:allowBackup="true"  
  15.         android:icon="@drawable/ic_launcher"  
  16.         android:label="@string/app_name"  
  17.         android:theme="@style/AppTheme" >  
  18.         <activity  
  19.             android:name="com.genwoxue.asynctask.MainActivity"  
  20.             android:label="@string/app_name" >  
  21.             <intent-filter>  
  22.                 <action android:name="android.intent.action.MAIN" />  
  23.   
  24.                 <category android:name="android.intent.category.LAUNCHER" />  
  25.             </intent-filter>  
  26.         </activity>  
  27.     </application>  
  28.   
  29. </manifest>  

 

注意:需要在AndroidManifest.xml文件中添加權限:

<uses-permission android:name="android.permission.INTERNET"/>

四、運行結果

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