android 異步加載解決方案 AsyncTask

Android應用開發過程中必須遵循單線程模型(Single Thread Model)的原則。因爲AndroidUI操作並不是線程安全的,所以涉及UI的操作必須在UI線程中完成。但是並非所有的操作都能在主線程中進行,Google工程師在設計上約定,Android應用在5s內無響應的話會導致ANR(Application Not Response),這就要求開發者必須遵循兩條法則:1、不能阻塞UI線程,2、確保只在UI線程中訪問Android UI工具包。於是,開啓子線程進行異步處理的技術方案應運而生。

以下是幾種異步處理方案:

一、AsyncTask (比handler 更輕量級)

AsyncTask簡介 AsyncTask的特點是任務在主線程之外運行,而回調方法是在主線程中執行,這就有效地避免了使用Handler帶來的麻煩。閱讀 AsyncTask的源碼可知,AsyncTask是使用java.util.concurrent 框架來管理線程以及任務的執行的,concurrent框架是一個非常 成熟,高效的框架,經過了嚴格的測試。這說明AsyncTask的設計很好的解決了匿名線程存在的問題。 AsyncTask是抽象類,其結構圖如下圖所示: AsyncTask定義了三種泛型類型 Params,Progress和Result。 Params 啓動任務執行的輸入參數,比如HTTP請求的URL。 Progress 後臺任務執行的百分比。 Result 後臺執行任務最終返回的結果,比如String。 子類必須實現抽象方法doInBackground(Params… p) ,在此方法中實現任務的執行工作,比如連接網絡獲取數據等。通常還應 該實現onPostExecute(Result r)方法,因爲應用程序關心的結果在此方法中返回。需要注意的是AsyncTask一定要在主線程中創 建實例。 AsyncTask的執行分爲四個步驟,每一步都對應一個回調方法,需要注意的是這些方法不應該由應用程序調用,開發者需要做的 就是實現這些方法。在任務的執行過程中,這些方法被自動調用,運行過程,如下圖所示: onPreExecute() 當任務執行之前開始調用此方法,可以在這裏顯示進度對話框。 doInBackground(Params…) 此方法在後臺線程執行,完成任務的主要工作,通常需要較長的時間。在執行過程中可以調用 publicProgress(Progress…)來更新任務的進度。 onProgressUpdate(Progress…) 此方法在主線程執行,用於顯示任務執行的進度。 onPostExecute(Result) 此方法在主線程執行,任務執行的結果作爲此方法的參數返回
There are a few threading rules that must be followed for this class to work properly: The AsyncTask class must be loaded on the UI thread. This is done automatically as of JELLY_BEAN. The task instance must be created on the UI thread. execute(Params...) must be invoked on the UI thread. Do not call onPreExecute(), onPostExecute(Result), doInBackground(Params...), onProgressUpdate(Progress...) manually. The task can be executed only once (an exception will be thrown if a second execution is attempted.)

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

  • Task的實例必須在UI thread中創建;
  • execute方法必須在UI thread中調用;
  • 不要手動的調用onPreExecute(), onPostExecute(Result),doInBackground(Params...), onProgressUpdate(Progress...)這幾個方法;
  • 該task只能被執行一次,否則多次調用時將會出現異常;

code : (網上例子 ,直接在主線程運行這個即可)
  1. package vic.wong.main;  
  2. import android.os.AsyncTask;  
  3. import android.widget.ProgressBar;  
  4. import android.widget.TextView;  
  5.   
  6. /**  
  7.  * 生成該類的對象,並調用execute方法之後  
  8.  * 首先執行的是onProExecute方法  
  9.  * 其次執行doInBackgroup方法  
  10.  *  
  11.  */  
  12. public class ProgressBarAsyncTask extends AsyncTask<Integer, Integer, String> {  
  13.   
  14.     private TextView textView;  
  15.     private ProgressBar progressBar;  
  16.       
  17.       
  18.     public ProgressBarAsyncTask(TextView textView, ProgressBar progressBar) {  
  19.         super();  
  20.         this.textView = textView;  
  21.         this.progressBar = progressBar;  
  22.     }  
  23.   
  24.   
  25.     /**  
  26.      * 這裏的Integer參數對應AsyncTask中的第一個參數   
  27.      * 這裏的String返回值對應AsyncTask的第三個參數  
  28.      * 該方法並不運行在UI線程當中,主要用於異步操作,所有在該方法中不能對UI當中的空間進行設置和修改  
  29.      * 但是可以調用publishProgress方法觸發onProgressUpdate對UI進行操作  
  30.      */  
  31.     @Override  
  32.     protected String doInBackground(Integer... params) {  
  33.         NetOperator netOperator = new NetOperator();  
  34.         int i = 0;  
  35.         for (i = 10; i <= 100; i+=10) {  
  36.             netOperator.operator();  
  37.             publishProgress(i);  
  38.         }  
  39.         return i + params[0].intValue() + "";  
  40.     }  
  41.   
  42.   
  43.     /**  
  44.      * 這裏的String參數對應AsyncTask中的第三個參數(也就是接收doInBackground的返回值)  
  45.      * 在doInBackground方法執行結束之後在運行,並且運行在UI線程當中 可以對UI空間進行設置  
  46.      */  
  47.     @Override  
  48.     protected void onPostExecute(String result) {  
  49.         textView.setText("異步操作執行結束" + result);  
  50.     }  
  51.   
  52.   
  53.     //該方法運行在UI線程當中,並且運行在UI線程當中 可以對UI空間進行設置  
  54.     @Override  
  55.     protected void onPreExecute() {  
  56.         textView.setText("開始執行異步線程");  
  57.     }  
  58.   
  59.   
  60.     /**  
  61.      * 這裏的Intege參數對應AsyncTask中的第二個參數  
  62.      * 在doInBackground方法當中,,每次調用publishProgress方法都會觸發onProgressUpdate執行  
  63.      * onProgressUpdate是在UI線程中執行,所有可以對UI空間進行操作  
  64.      */  
  65.     @Override  
  66.     protected void onProgressUpdate(Integer... values) {  
  67.         int vlaue = values[0];  
  68.         progressBar.setProgress(vlaue);  
  69.     }  
  70.   
  71.       
  72.       
  73.       
  74.   
  75. }  
    
發佈了9 篇原創文章 · 獲贊 0 · 訪問量 9851
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章