AsyncTask簡單介紹

在開發Android應用時必須遵照單線程模型的原則: Android UI操做並非線程安全的而且這些操做必須在UI線程中執行。在單線程模型中始終要記住兩條法則: 
1. 不要阻塞UI線程 
2. 確保只在UI線程中訪問Android UI工具包 
      當一個程序第一次啓動時,Android會同時啓動一個對應的主線程(Main Thread),主線程主要負責處理與UI相關的事件,如:用戶的按鍵事件,用戶接觸屏幕的事件以及屏幕繪圖事件,並把相關的事件分發到對應的組件進行處理。因此主線程一般又被叫作UI線程。 
      好比說從網上獲取一個網頁,在一個TextView中將其源代碼顯示出來,這種涉及到網絡操做的程序通常都是須要開一個線程完成網絡訪問,可是在得到頁面源碼後,是不能直接在網絡操做線程中調用TextView.setText()的.由於其餘線程中是不能直接訪問主UI線程成員 。
android提供了幾種在其餘線程中訪問UI線程的方法。 
Activity.runOnUiThread( Runnable ) 
View.post( Runnable ) 
View.postDelayed( Runnable, long ) 
Hanlder 
這些類或方法一樣會使你的代碼很複雜很難理解。然而當你須要實現一些很複雜的操做並須要頻繁地更新UI時這會變得更糟糕。 

     爲了解決這個問題,Android 1.5提供了一個工具類:AsyncTask,它使建立須要與用戶界面交互的長時間運行的任務變得更簡單。相對來講AsyncTask更輕量級一些,適用於簡單的異步處理,不須要藉助線程和Handler便可實現。 
AsyncTask是抽象類.AsyncTask定義了三種泛型類型 Params,Progress和Result。 
  Params 啓動任務執行的輸入參數,好比HTTP請求的URL。 
  Progress 後臺任務執行的百分比。 
  Result 後臺執行任務最終返回的結果,好比String。 

     AsyncTask的執行分爲四個步驟,每一步都對應一個回調方法,這些方法不該該由應用程序調用,開發者須要作的就是實現這些方法。 
  1) 子類化AsyncTask 
  2) 實現AsyncTask中定義的下面一個或幾個方法 
     onPreExecute(), 該方法將在執行實際的後臺操做前被UI thread調用。能夠在該方法中作一些準備工做,如在界面上顯示一個進度條。 
    doInBackground(Params...), 將在onPreExecute 方法執行後立刻執行,該方法運行在後臺線程中。這裏將主要負責執行那些很耗時的後臺計算工做。能夠調用 publishProgress方法來更新實時的任務進度。該方法是抽象方法,子類必須實現。 
    onProgressUpdate(Progress...),在publishProgress方法被調用後,UI thread將調用這個方法從而在界面上展現任務的進展狀況,例如經過一個進度條進行展現。 
    onPostExecute(Result), 在doInBackground 執行完成後,onPostExecute 方法將被UI thread調用,後臺的計算結果將經過該方法傳遞到UI thread. 

爲了正確的使用AsyncTask類,如下是幾條必須遵照的準則: 
  1) Task的實例必須在UI thread中建立 
  2) execute方法必須在UI thread中調用 
  3) 不要手動的調用onPreExecute(), onPostExecute(Result),doInBackground(Params...), onProgressUpdate(Progress...)這幾個方法 
  4) 該task只能被執行一次,不然屢次調用時將會出現異常 
      doInBackground方法和onPostExecute的參數必須對應,這兩個參數在AsyncTask聲明的泛型參數列表中指定,第一個爲doInBackground接受的參數,第二個爲顯示進度的參數,第第三個爲doInBackground返回和onPostExecute傳入的參數。

從網上獲取一個網頁,在一個TextView中將其源代碼顯示出來


package  test.list;
import  java.io.ByteArrayOutputStream;
import  java.io.InputStream;
import  java.util.ArrayList;

import  org.apache.http.HttpEntity;
import  org.apache.http.HttpResponse;
import  org.apache.http.client.HttpClient;
import  org.apache.http.client.methods.HttpGet;
import  org.apache.http.impl.client.DefaultHttpClient;

import  android.app.Activity;
import  android.app.ProgressDialog;
import  android.content.Context;
import  android.content.DialogInterface;
import  android.os.AsyncTask;
import  android.os.Bundle;
import  android.os.Handler;
import  android.os.Message;
import  android.view.View;
import  android.widget.Button;
import  android.widget.EditText;
import  android.widget.TextView;

public   class  NetworkActivity  extends  Activity{
    
private  TextView message;
    
private  Button open;
    
private  EditText url;

    @Override
    
public   void  onCreate(Bundle savedInstanceState) {
       
super .onCreate(savedInstanceState);
       setContentView(R.layout.network);
       message
=  (TextView) findViewById(R.id.message);
       url
=  (EditText) findViewById(R.id.url);
       open
=  (Button) findViewById(R.id.open);
       open.setOnClickListener(
new  View.OnClickListener() {
           
public   void  onClick(View arg0) {
              connect();
           }
       });

    }

    
private   void  connect() {
        PageTask task 
=   new  PageTask( this );
        task.execute(url.getText().toString());
    }


    
class  PageTask  extends  AsyncTask < String, Integer, String >  {
        
//  可變長的輸入參數,與AsyncTask.exucute()對應
        ProgressDialog pdialog;
        
public  PageTask(Context context){
            pdialog 
=   new  ProgressDialog(context,  0 );   
            pdialog.setButton(
" cancel " new  DialogInterface.OnClickListener() {
             
public   void  onClick(DialogInterface dialog,  int  i) {
              dialog.cancel();
             }
            });
            pdialog.setOnCancelListener(
new  DialogInterface.OnCancelListener() {
             
public   void  onCancel(DialogInterface dialog) {
              finish();
             }
            });
            pdialog.setCancelable(
true );
            pdialog.setMax(
100 );
            pdialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
            pdialog.show();


        }
        @Override
        
protected  String doInBackground(String... params) {

            
try {

               HttpClient client 
=   new  DefaultHttpClient();
               
//  params[0]表明鏈接的url
               HttpGet get  =   new  HttpGet(params[ 0 ]);
               HttpResponse response 
=  client.execute(get);
               HttpEntity entity 
=  response.getEntity();
               
long  length  =  entity.getContentLength();
               InputStream is 
=  entity.getContent();
               String s 
=   null ;
               
if (is  !=   null ) {
                   ByteArrayOutputStream baos 
=   new  ByteArrayOutputStream();

                   
byte [] buf  =   new   byte [ 128 ];

                   
int  ch  =   - 1 ;

                   
int  count  =   0 ;

                   
while ((ch  =  is.read(buf))  !=   - 1 ) {

                      baos.write(buf, 
0 , ch);

                      count 
+=  ch;

                      
if (length  >   0 ) {
                          
//  若是知道響應的長度,調用publishProgress()更新進度
                          publishProgress(( int ) ((count  /  ( float ) length)  *   100 ));
                      }

                      
//  讓線程休眠100ms
                      Thread.sleep( 100 );
                   }
                   s 
=   new  String(baos.toByteArray());              }
               
//  返回結果
                return  s;
            } 
catch (Exception e) {
               e.printStackTrace();

            }

            
return   null ;

        }

        @Override
        
protected   void  onCancelled() {
            
super .onCancelled();
        }

        @Override
        
protected   void  onPostExecute(String result) {
            
//  返回HTML頁面的內容
            message.setText(result);
            pdialog.dismiss(); 
        }

        @Override
        
protected   void  onPreExecute() {
            
//  任務啓動,能夠在這裏顯示一個對話框,這裏簡單處理
            message.setText(R.string.task_started);
        }

        @Override
        
protected   void  onProgressUpdate(Integer... values) {
            
//  更新進度
              System.out.println( "" + values[ 0 ]);
              message.setText(
"" + values[ 0 ]);
              pdialog.setProgress(values[
0 ]);
        }

     }

}


 

最後須要說明AsyncTask不能徹底取代線程,在一些邏輯較爲複雜或者須要在後臺反覆執行的邏輯就可能須要線程來實現了。java

相關文章
相關標籤/搜索