AsyncTask深入理解

yangxi_001發表於2014-01-16

/**
 * 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類,以下是幾條必須遵守的準則:
       0) AsyncTask的實現當中必須例項化doInBackground()方法,其他的不規定
  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<Integer, Integer, String>當中,<>內三個型別可以是隨意的,根據實際情況而定
 * 但必須的遵循一些規則,下面以AsyncTask<Integer, Integer, String>為例子說明
 * 第一個Integer為doInBackground()輸入引數的型別
 * 第二個Integer為onProgressUpdate()輸入引數的型別
 * 第三個String為doInBackground()的返回值型別和onProgressUpdate()的輸入引數型別
 * 必須的例項化doInBackground()方法,其他,可有可無,根據實際情況
*/
class DownloadTask extends AsyncTask<Integer, Integer, String> {
 
 //注意:該方法是執行在UI執行緒當中的,此時還允許對UI當中的控制元件進行操作,不同於doInBackground()方法
 @Override
 protected void onPreExecute() {
  //第一個執行方法
  //do what u want
  super.onPreExecute();
 }
 
 //doInBackground()作為另外一個獨立的執行緒執行的了,並不再執行於UI執行緒當中了,所以不能對UI當中的控制元件進行設定和修改
 //等等操作了,這一點是不同於onPreExecute()方法,但可以通過publishProgress()方法間接的觸發呼叫可執行於UI執行緒當中
 //的onProgressUpdate()來對UI執行緒當中的控制元件進行操作,publishProgress()方法自動觸發onProgressUpdate()方法
 //(Integer... params)為execute(100)傳入的可變長引數,輸入引數的個數可不定,型別為<>當中的第一個型別,
 //params[0]表示第一輸入引數,params[1]表示第二個,以此類推
 //doInBackground()方法執行完後會自動觸發onPostExecute()方法,它的返回值即為onPostExecute()方法的輸入引數
 @Override
 protected String doInBackground(Integer... params) {
  //第二個執行方法,onPreExecute()執行完後執行
  //do what u want
  return "一個字元";
 }

 //每一次呼叫publishProgress()方法都會自動觸發呼叫onProgressUpdate()方法,而在doInBackground()當中,又常常是
 //用到publishProgress()方法,實現與UI執行緒之間資料的實時互動
 //onProgressUpdate()和onPreExecute()一樣,都是執行在UI執行緒當中的,換言之,都可以對UI執行緒當中的控制程式操作
 @Override
 protected void onProgressUpdate(Integer... progress) {
  //do what u want
  super.onProgressUpdate(progress);
 }

 //onPostExecute()在doInBackground()方法執行完後自動觸發呼叫,注意onPostExecute()是執行於UI執行緒當中的
 //onPostExecute(String result)當中傳入的引數即為doInBackground()方法的返回值
 @Override
 protected void onPostExecute(String result) {
  //doInBackground返回時觸發,換句話說,就是doInBackground執行完後觸發
  //do what u want
  super.onPostExecute(result);
 }
 
}