Android筆記二十六.Android非同步任務處理(AsyncTask)

來源:互聯網
上載者:User

標籤:android應用

轉載請表明出處:http://blog.csdn.net/u012637501(嵌入式_小J的天空)
一、引言    我們知道Android的UI線程主要負責處理使用者的按鍵事件、使用者觸屏事件及螢幕繪圖事件等,對於其他的操作盡量不要在UI線程中實現,因為這些操作很有可能會阻塞UI線程,比如一些耗時操作,會導致UI介面停止回應,從而降低了使用者的體驗。所以,為了避免UI線程失去響應的問題,Android建議將耗時操作放在新線程中完成,但新線程也可能需要動態更新UI組件:比如需要從網上擷取一個網頁,然後在TextView中將其原始碼顯示出來,此時就應該將串連網路,擷取網路資料的操作(耗時)放在新線程中完成。    但是,問題來了:當擷取網路資料之後,由於新線程不允許直接更新UI組件,我們該如何更新UI組件資料呢?為瞭解決新線程不能更新UI組件問題,Android提供了如下幾種解決方案:(1)使用Handler訊息傳遞機制實現線程之間的通訊(如上一篇文章所述);(2)Activity.runOnUiThread(Runnable);(3)View.post(Runnable);(4)View.postDelayed(Runnable long);(5)非同步任務。又由於(2)~(4)方式有可能導致編程有點繁瑣,而非同步任務則可簡化這種操作。 二、AsyncTask簡介    Android的類AsyncTask對線程間通訊進行了封裝,提供了簡易的編程方式使後台線程和UI線程進行通訊:後台線程執行非同步任務,並把操作結果通知UI。不再需要子線程和Handler就可以完成非同步作業並且重新整理使用者介面。 1.AsyncTask類    AsyncTask<>是一個抽象類別,通常用於被繼承,繼承AsyncTask時需要指定如下三種泛型參數:(1)Params:啟動任務執行輸入參數的類型;(2)Progress:背景工作完成的進度值(百分比)的類型;(3)Result:後台執行任務完成後返回結果的類型,如String、Integer; 2.Async類中主要方法(1)onPreExecute():該方法將在執行實際的後台操作前被UI線程調用。可以在該方法中做一些準備工作,如在介面上顯示一個進度條,或者一些控制項的執行個體化,這個方法可以不用實現。-----(UI線程調用,後台線程未啟動,初始化工作)(2)doInBackground(Params...values):將在onPreExecute 方法執行後馬上執行,該方法運行在後台線程中。這裡將主要負責執行那些比較耗時的幕後處理工作。可以調用 publishProgress()方法來即時更新任務進度。該方法是抽象方法,子類必須實現。-----(後台線程調用,執行背景工作)
(3)onProgressUpdate(Progress...values):在publishProgress方法被調用後,UI 線程將調用這個方法從而在介面上展示任務的進展情況,例如通過一個進度條進行展示。-----(UI線程調用,展現背景工作進展)
(4)onPostExecute(Result):在doInBackground 執行完成後,onPostExecute 方法將被UI線程調用,背景計算結果(doInBackground方法返回值)將通過該方法傳遞到UI線程,並且在介面上展示給使用者。-----(UI線程調用,顯示後台線程運行結果)(5) onCancelled():在使用者取消線程操作的時候調用。在主線程中調用onCancelled()的時候調用。-----(UI線程調用,取消後台線程)  三、非同步任務處理開發步驟1.建立AsyncTask的子類,並為三個泛型參數指定類型。如果某個泛型參數不需要指定類型,則將它指定為Void。2.根據需要實現AsyncTask上述五中方法;3.調用AsyncTask子類的執行個體的execute(Params... params)開始執行耗時任務。另外,使用AsyncTask類需要遵守的以下準則:(1)Task的執行個體必須在UI線程中建立;(2)execute(Params...)方法必須在UI線程中調用;(3)不要手動的調用onPreExecute(), onPostExecute(Result),doInBackground(Params...),onProgressUpdate(Progress...)這幾個方法,需要在UI線程中執行個體化這個task來調用;(4)該task只能被執行一次,否者多次調用時將會出現異常。 四、源碼實戰 1.實現功能 2.源碼實現 (1)MainActivity.java功能:用以擷取介面組件,執行個體化一個AsyncTask子類對象並調用其exeute(Integer....params)方法以指定參數params運行一個任務。
package com.example.android_asynctask;import android.app.Activity;import android.os.Bundle;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.ProgressBar;import android.widget.TextView;public class MainActivity extends Activity { private Button downbtn; private TextView textView; private ProgressBar progressBar;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.main);        downbtn = (Button)findViewById(R.id.download);        textView = (TextView)findViewById(R.id.text);        progressBar = (ProgressBar)findViewById(R.id.progressBar);        final DownloadTest download = new DownloadTest(textView,progressBar);//擷取一個DownloadTest對象,並傳遞組件對象參數        downbtn.setOnClickListener(new OnClickListener()        {   @Override   public void onClick(View v) {    download.execute(200);   }        });           }}
(2)DownloadTest.java功能:繼承於AsyncTask的子類,其中onPreExecute()作用是為運行後台線程(子線程)完成初始化工作;doInBackground方法運行後台線程;onProgressUpdate方法更新UI;onPostExecute方法處理後台線程運行結果。
package com.example.android_asynctask;import android.graphics.Color;import android.os.AsyncTask;import android.view.View;import android.widget.ProgressBar;import android.widget.TextView;public class DownloadTest extends AsyncTask<Integer,Integer,String>{ private TextView tv; private ProgressBar pb; //帶參數構造方法 DownloadTest(TextView text,ProgressBar bar) {  this.tv = text;  this.pb = bar; } //不帶參數構造方法 DownloadTest() { } /*1.onPreExecute方法  * 為子線程(後台)運行初始化相關內容  */ protected void onPreExecute() {      tv.setVisibility(View.VISIBLE); //設定顯示文本組件      pb.setVisibility(View.VISIBLE); //設定顯示進度條      super.onPreExecute(); } /*2.doInBackground方法  *  運行一個後台線程,該線程實現每arg0[0]毫秒調用一次onProgressUpdate方法  */ protected String doInBackground(Integer... arg0) {  for(int i=0;i<100;i++)  {   publishProgress(i); //調用onProgressUpdate方法並傳遞參數i   try {    Thread.sleep(arg0[0]);//累加一次,線程休眠argo[0]毫秒   } catch (InterruptedException e) {    e.printStackTrace();   }  }  return "下載完畢"; //後檯子線程運行完畢後,返回的值 } /*3.onProgressUpdate方法  * 調用publishProgress(i)時調用該方法,並傳遞參數i給形參values[0]*/ @Override protected void onProgressUpdate(Integer... values) {  pb.setProgress(values[0]); //設定進度條值  tv.setText("已經下載"+values[0]+"%"); //文本組件顯示提示資訊  super.onProgressUpdate(values); } /*4.onPostExecute  * 處理後台線程得到的結果  * */ protected void onPostExecute(String result) {  pb.setVisibility(View.INVISIBLE);//隱藏進度條  tv.setVisibility(View.VISIBLE);//顯示UI文本顯示框組件  tv.setText(result);  tv.setTextSize(20);  tv.setTextColor(Color.RED);  super.onPostExecute(result); }}


效果示範:

源碼分析:    通過源碼我們可以知道,主線程通過調用AsyncTask子類的execute()方法,進而調用AsyncTask子類的onPreExecute方法,用以再運行後台線程之前為其初始化相關內容。然後,在新建立的子線程中調用doInBackground()方法實現後台線程功能並通過publishProgress()方法調用onProgressUpdate()方法更新UI內容,最後在主線中執行onPostExecute方法來處理後台線程啟動並執行結果。注意:其中只有doInBackground()方法,以及publishProgress()方法是在子線程中執行的,其他的方法都是在主線程中執行的,所以可以在這些方法中更新介面組件。

Android筆記二十六.Android非同步任務處理(AsyncTask)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.