Android AsyncTask的使用詳解

當然,我們在進行耗時操作或者更新UI時,是可以使用匿名線程的,但是此種方式是存在缺陷的:第一,線程的開銷較大,如果每個任務都要創建一個線程,那麼應用 程序的效率要低很多;第二,線程無法管理,匿名線程創建並啓動後就不受程序的控制了,如果有很多個請求發送,那麼就會啓動非常多的線程,系統將不堪重負。 另外,前面已經看到,在新線程中更新UI還必須要引入handler,這讓代碼看上去非常臃腫。

所以建議使用AsyncTask異步線程:AsyncTask的特點是任務在主線程之外運行,而回調方法是在主線程中執行,這就有效地避免了使用Handler帶來的麻煩。

AsyncTask是抽象類,子類必須實現抽象方法doInBackground(Params... p) ,在此方法中實現任務的執行工作,比如連接網絡獲取數據等。通常還應該實現onPostExecute(Result r)方法,因爲應用程序關心的結果在此方法中返回。需要注意的是AsyncTask一定要在主線程中創建實例。AsyncTask定義了三種泛型類型 Params,Progress和Result。

* Params 啓動任務執行的輸入參數,比如HTTP請求的URL。
* Progress 後臺任務執行的百分比。
* Result 後臺執行任務最終返回的結果,比如String。

 

效果如圖:(加載雅虎天氣---耗時操作)

 

 

 

 

具體代碼如下:

/**
 * 使用AsyncTask異步線程
 * @author 張進
 *
 */
public class NetActivity extends Activity {

 //雅虎天氣的URL
 private static final String HttpUrl = "http://xml.weather.yahoo.com/forecastrss?u=c&p=CHXX0008";
 
 private TextView tv ;
 
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  
  Log.i("NetActivity", Thread.currentThread().getId()+"");
  
  LinearLayout mLinearLayout = new LinearLayout(this);
  mLinearLayout.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
  mLinearLayout.setGravity(Gravity.CENTER);
  
  tv = new TextView(this);
  tv.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
  
  mLinearLayout.addView(tv);
  setContentView(mLinearLayout);
  
  //執行異步線程
  PageTask task = new PageTask(this);  
  task.execute(HttpUrl);
  
 }

 class PageTask extends AsyncTask<String, Integer, String> {

  ProgressDialog mProgressDialog = null ;
  Context mContext ;
  
  public PageTask(Context context){
   mContext = context;
  }
  
  //此方法在主線程執行,當任務執行之前開始調用此方法,可以在這裏顯示進度對話框
  @Override
  protected void onPreExecute() {
   super.onPreExecute();
   Log.i("PageTask", "onPreExecute()  "+Thread.currentThread().getId());
   mProgressDialog = new ProgressDialog(mContext);
   mProgressDialog.setTitle("請稍等...");
   mProgressDialog.setMessage("數據加載中");

   //長方形進度條
   mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
   //精度條的長度
   mProgressDialog.setMax(100);
   //設置爲不明確進度
   mProgressDialog.setIndeterminate(false);
   mProgressDialog.show();
  }
  
  //此方法在後臺線程執行,完成任務的主要工作,通常需要較長的時間。
  //在執行過程中可以調用publicProgress(Progress...)來更新任務的進度。

  @Override
  protected String doInBackground(String... params) {  
            Log.i("PageTask", "doInBackground... "+Thread.currentThread().getId());
   try {  
                HttpClient client = new DefaultHttpClient();  
                // params[0] 代表連接的url  
                HttpGet get = new HttpGet(params[0]);  
                HttpResponse response = client.execute(get); 
                
                //網路連接通
                if(response.getStatusLine().getStatusCode()==HttpStatus.SC_OK){   
                  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));  
                             }  
                             // 爲了在模擬器中清楚地看到進度,讓線程休眠1000ms  
                             Thread.sleep(2000);  
                         }  
                         return new String(baos.toByteArray());  
                     }
                    
                }
                //網絡連接不通
                else{   
                 return "網絡連接不通";
                }    
                
            } catch (Exception e) {  
                e.printStackTrace();  
            }  
            return null;  
        }  

  
  //此方法在主線程執行,用於顯示任務執行的進度
  @Override
  protected void onProgressUpdate(Integer... values) {
   super.onProgressUpdate(values);
   Log.i("PageTask", "onProgressUpdate()  "+Thread.currentThread().getId());
   NetActivity.this.setTitle("加載了  "+values[0]+"%");
   mProgressDialog.setProgress(values[0]);//更新進度條進度
  }  
  
  
  //此方法在主線程執行,任務執行的結果作爲此方法的參數返回。
  @Override
  protected void onPostExecute(String result) {
   tv.setText(result);
   Log.i("PageTask", "onPostExecute()  "+Thread.currentThread().getId());
   mProgressDialog.dismiss();
  }
  
 }
 
}

 


 

發佈了27 篇原創文章 · 獲贊 70 · 訪問量 36萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章