Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android_AsyncTask詳解及其應用(一)

Android_AsyncTask詳解及其應用(一)

編輯:關於Android編程

    之前介紹了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]
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> { 
    protected Long doInBackground(URL... urls) { 
        int count = urls.length; 
        long totalSize = 0; 
        for (int i = 0; i < count; i++) { 
            totalSize += Downloader.downloadFile(urls[i]); 
            publishProgress((int) ((i / (float) count) * 100)); 
            // Escape early if cancel() is called  
            if (isCancelled()) break; 
        } 
        return totalSize; 
    } 
 
    protected void onProgressUpdate(Integer... progress) { 
        setProgressPercent(progress[0]); 
    } 
 
    protected void onPostExecute(Long result) { 
        showDialog("Downloaded " + result + " bytes"); 
    } 

 private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
     protected Long doInBackground(URL... urls) {
         int count = urls.length;
         long totalSize = 0;
         for (int i = 0; i < count; i++) {
             totalSize += Downloader.downloadFile(urls[i]);
             publishProgress((int) ((i / (float) count) * 100));
             // Escape early if cancel() is called
             if (isCancelled()) break;
         }
         return totalSize;
     }

     protected void onProgressUpdate(Integer... progress) {
         setProgressPercent(progress[0]);
     }

     protected void onPostExecute(Long result) {
         showDialog("Downloaded " + result + " bytes");
     }
 }
            一旦創建,執行一個任務非常簡單:
[java]
new DownloadFilesTask().execute(url1, url2, url3); 

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]
package com.example.asynctaskdemo; 
 
import android.app.Activity; 
import android.os.AsyncTask; 
import android.os.Bundle; 
import android.view.View; 
import android.widget.Button; 
import android.widget.ProgressBar; 
import android.widget.TextView; 
 
public class Asy1Activity extends Activity { 
 
    Button download; 
    ProgressBar pb; 
    TextView tv; 
 
    /** Called when the activity is first created. */ 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.asy1); 
        pb = (ProgressBar) findViewById(R.id.pb); 
        tv = (TextView) findViewById(R.id.tv); 
 
        download = (Button) findViewById(R.id.download); 
        download.setOnClickListener(new View.OnClickListener() { 
            @Override 
            public void onClick(View v) { 
                DownloadTask task=new DownloadTask(); 
                task.execute(100); 
            } 
        }); 
    } 
    class DownloadTask extends AsyncTask<Integer, Integer, String>{ 
 
        @Override 
        protected void onCancelled() { 
            // TODO Auto-generated method stub  
            super.onCancelled(); 
        } 
 
        @Override 
        protected void onPostExecute(String result) { 
            setTitle(result);  
            super.onPostExecute(result); 
        } 
 
        @Override 
        protected void onPreExecute() { 
            // TODO Auto-generated method stub  
            super.onPreExecute(); 
        } 
 
        @Override 
        protected void onProgressUpdate(Integer... values) { 
            // TODO Auto-generated method stub  
            super.onProgressUpdate(values); 
            tv.setText(values[0]+"%"); 
             
        } 
 
        @Override 
        protected String doInBackground(Integer... params) { 
            for(int i=0;i<=100;i++){ 
                pb.setProgress(i); 
                publishProgress(i);   
                 try {   
                        Thread.sleep(params[0]);   
                    } catch (InterruptedException e) {   
                        e.printStackTrace();   
                    }   
            } 
            return "執行完畢"; 
        } 
         
    } 
     

package com.example.asynctaskdemo;

import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;

public class Asy1Activity extends Activity {

 Button download;
 ProgressBar pb;
 TextView tv;

 /** Called when the activity is first created. */
 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.asy1);
  pb = (ProgressBar) findViewById(R.id.pb);
  tv = (TextView) findViewById(R.id.tv);

  download = (Button) findViewById(R.id.download);
  download.setOnClickListener(new View.OnClickListener() {
   @Override
   public void onClick(View v) {
    DownloadTask task=new DownloadTask();
    task.execute(100);
   }
  });
 }
 class DownloadTask extends AsyncTask<Integer, Integer, String>{

  @Override
  protected void onCancelled() {
   // TODO Auto-generated method stub
   super.onCancelled();
  }

  @Override
  protected void onPostExecute(String result) {
   setTitle(result);
   super.onPostExecute(result);
  }

  @Override
  protected void onPreExecute() {
   // TODO Auto-generated method stub
   super.onPreExecute();
  }

  @Override
  protected void onProgressUpdate(Integer... values) {
   // TODO Auto-generated method stub
   super.onProgressUpdate(values);
   tv.setText(values[0]+"%");
   
  }

  @Override
  protected String doInBackground(Integer... params) {
   for(int i=0;i<=100;i++){
    pb.setProgress(i);
    publishProgress(i); 
     try { 
                     Thread.sleep(params[0]); 
                 } catch (InterruptedException e) { 
                     e.printStackTrace(); 
                 } 
   }
   return "執行完畢";
  }
  
 }
 
}                                                                                                  

         1、一個從網絡下載圖片的例子

[java]
package com.example.asynctaskdemo; 
 
import java.io.ByteArrayOutputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import java.net.HttpURLConnection; 
import java.net.MalformedURLException; 
import java.net.URL; 
import android.app.Activity; 
import android.graphics.Bitmap; 
import android.graphics.BitmapFactory; 
import android.os.AsyncTask; 
import android.os.Bundle; 
import android.view.View; 
import android.view.View.OnClickListener; 
import android.widget.Button; 
import android.widget.ImageView; 
import android.widget.ProgressBar; 
 
public class Asy2Activity extends Activity { 
 
    private Button button; 
    private ProgressBar progressBar; 
    private ImageView imageView; 
    private final String imageUrl = "http://avatar.csdn.net/D/1/4/1_wangjinyu501.jpg"; 
 
    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
        // TODO Auto-generated method stub  
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.asy2); 
        initView(); 
    } 
 
    private void initView() { 
        button = (Button) findViewById(R.id.button); 
        button.setOnClickListener(new OnClickListener() { 
 
            @Override 
            public void onClick(View arg0) { 
                AsyncTaskLoadImage asyncTaskLoadImage = new AsyncTaskLoadImage(); 
 
                asyncTaskLoadImage.execute(imageUrl); 
            } 
        }); 
        progressBar = (ProgressBar) findViewById(R.id.pb); 
        imageView = (ImageView) findViewById(R.id.imageview); 
 
    } 
 
    class AsyncTaskLoadImage extends AsyncTask<String, Integer, Bitmap> { 
 
        @Override 
        protected void onPreExecute() { 
            super.onPreExecute(); 
 
        } 
 
        @Override 
        protected Bitmap doInBackground(String... params) { 
            Bitmap bitmap = null; 
            try { 
                URL url = new URL(params[0]); 
                HttpURLConnection urlConnection = (HttpURLConnection) url 
                        .openConnection(); 
                urlConnection.connect(); 
                int MAX = urlConnection.getContentLength(); 
                progressBar.setMax(MAX); 
 
                InputStream inputStream = urlConnection.getInputStream(); 
 
                ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); 
                byte[] b = new byte[1024]; 
                int len = 0; 
                int processBarNum = 0; 
                while ((len = inputStream.read(b)) != -1) { 
                    byteArrayOutputStream.write(b, 0, len); 
                    processBarNum += len; 
                    publishProgress(processBarNum); 
                } 
               // bitmap = BitmapFactory.decodeStream(inputStream);  
                bitmap = BitmapFactory.decodeByteArray( 
                        byteArrayOutputStream.toByteArray(), 0, MAX); 
                inputStream.close(); 
            } catch (MalformedURLException e) { 
                e.printStackTrace(); 
            } catch (IOException e) { 
                e.printStackTrace(); 
            } 
            return bitmap; 
        } 
 
        @Override 
        protected void onProgressUpdate(Integer... values) { 
            progressBar.setProgress(values[0]); 
            super.onProgressUpdate(values); 
 
        } 
 
        @Override 
        protected void onPostExecute(Bitmap result) { 
 
            imageView.setImageBitmap(result); 
            super.onPostExecute(result); 
        } 
 
    } 
 

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