步步爲營_Android開發課[8]_AsyncTask學習

Focus on technology, enjoy life!—— QQ:804212028
瀏覽鏈接:http://blog.csdn.net/y18334702058/article/details/44624305


  • 主題:AsyncTask學習

    -在開發Android移動客戶端的時候往往要使用多線程來進行操作,我們通常會將耗時的操作放在單獨的線程執行,避免其佔用主線程而給用戶帶來不好的用戶體驗。但是在子線程中無法去操作主線程(UI線程),在子線程中操作UI線程會出現錯誤。因此android提供了一個類Handler來在子線程中來更新UI線程,用發消息的機制更新UI界面,呈現給用戶。這樣就解決了子線程更新UI的問題。但是費時的任務操作總會啓動一些匿名的子線程,太多的子線程給系統帶來巨大的負擔,隨之帶來一些性能問題。因此android提供了一個工具類AsyncTask,顧名思義異步執行任務。這個AsyncTask生來就是處理一些後臺的比較耗時的任務,給用戶帶來良好用戶體驗的,從編程的語法上顯得優雅了許多,不再需要子線程和Handler就可以完成異步操作並且刷新用戶界面。

AsyncTask 的優勢:

1、線程的開銷較大,如果每個任務都要創建一個線程,那麼應用程 序的效率要低很多;
2、線程無法管理,匿名線程創建並啓動後就不受程序的控制了,如果有很多個請求發送,那麼就會啓動非常多的線程,系統將不堪重負。
3、另外,前面已經看到,在新線程中更新UI還必須要引入handler,這讓代碼看上去非常臃腫。

AsyncTask定義了三種泛型類型

他們分別是Params,Progress和Result。

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

 AsyncTask的執行分爲四個步驟,每一步都對應一個回調方法,這些方法不應該由應用程序調用,開發者需要做的就是實現這些方法。 

  1) 子類化AsyncTask
  2) 實現AsyncTask中定義的下面一個或幾個方法
   onPreExecute(), 該方法將在執行實際的後臺操作前被UI thread調用。可以在該方法中做一些準備工作,如在界面上顯示一個進度條。
   doInBackground(Params…), 將在onPreExecute 方法執行後馬上執行,該方法運行在後臺線程中。這裏將主要負責執行那些很耗時的後臺計算工作。可以調用 publishProgress方法來更新實時的任務進度。該方法是抽象方法,子類必須實現。
   onProgressUpdate(Progress…),在publishProgress方法被調用後,UI thread將調用這個方法從而在界面上展示任務的進展情況,例如通過一個進度條進行展示。
   onPostExecute(Result), 在doInBackground 執行完成後,onPostExecute 方法將被UI thread調用,後臺的計算結果將通過該方法傳遞到UI thread.

爲了正確的使用AsyncTask類,以下是幾條必須遵守的準則:
  1) Task的實例必須在UI thread中創建
  2) execute方法必須在UI thread中調用
  3) 不要手動的調用onPreExecute(), onPostExecute(Result),doInBackground(Params…), onProgressUpdate(Progress…)這幾個方法
  4) 該task只能被執行一次,否則多次調用時將會出現異常
doInBackground方法和onPostExecute的參數必須對應,這兩個參數在AsyncTask聲明的泛型參數列表中指定,第一個爲doInBackground接受的參數,第二個爲顯示進度的參數,第第三個爲doInBackground返回和onPostExecute傳入的參數。

AsyncTask幾點要注意的地方

問題1:AsyncTask是多線程嗎?

答:是。

問題2:AsyncTask與Handler相比,誰更輕量級?

答:通過看源碼,發現AsyncTask實際上就是一個線程池,而網上的說法是AsyncTask比handler要輕量級,顯然上不準確的,只能這樣說,AsyncTask在代碼上比handler要輕量級別,而實際上要比handler更耗資源,因爲AsyncTask底層是一個線程池!而Handler僅僅就是發送了一個消息隊列,連線程都沒有開。
但是,如果異步任務的數據特別龐大,AsyncTask這種線程池結構的優勢就體現出來了。

AsyncTask更改主線程UI顯示

package com.example.asynctaskdemo;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class MainActivity extends Activity {

    private TextView tv;
    private Button openButton;
    private EditText url;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        tv = (TextView) findViewById(R.id.tv);
        url = (EditText) findViewById(R.id.url);
        openButton = (Button) findViewById(R.id.openButton);
        openButton.setOnClickListener(new View.OnClickListener() {
            public void onClick(View arg0) {
                connect();
            }
        });
    }
    private void connect() {
        PageTask task = new PageTask(this);
        task.execute(url.getText().toString()); 

    }

    class PageTask extends AsyncTask<String, Integer, String> {
        // 這三個參數對應的是excute(String),onProgressUpdate(Integer),onPostResult(string)這三個方法裏面的參數類型
        ProgressDialog pdialog;
        public PageTask(Context context) {
            pdialog = new ProgressDialog(context, 0);
            pdialog.setButton("cancel", new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int i) {
                    dialog.cancel();
                }
            });
            pdialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
                public void onCancel(DialogInterface dialog) {
                    finish();
                }
            });
            pdialog.setCancelable(true);
            pdialog.setMax(100);
            pdialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
            pdialog.show();
        }
        @Override
        protected String doInBackground(String... params) { // 用來接受excute(String)裏面的參數
            try {
                int i = 0;
                while (i <= 100) {
                    publishProgress(i++); // 這個方法是異步機制本來就存在的
                    Thread.sleep(1000);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return "下載完成";
        }


        @Override
        protected void onCancelled() {
            super.onCancelled();
        }
        @Override
        protected void onPostExecute(String result) { // 這個參數是接受doInBackgound()的返回值的
            // 返回HTML頁面的內容
            tv.setText(result);
            // pdialog.dismiss();
        }
        @Override
        protected void onPreExecute() {
            // 任務啓動,可以在這裏顯示一個對話框,這裏簡單處理
            tv.setText("開始下載");
        }
        @Override
        protected void onProgressUpdate(Integer... values) { // 這個參數是接受publishProgress(Integer)的參數的
            // 更新進度
            System.out.println("" + values[0]);
            tv.setText("" + values[0]);
            pdialog.setProgress(values[0]);
        }
    }
}

這是運行結果:
這裏寫圖片描述

Focus on technology, enjoy life!—— QQ:804212028
瀏覽鏈接:http://blog.csdn.net/y18334702058/article/details/44624305

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