Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android開發筆記之網絡編程—異步加載(AsyncTask)

android開發筆記之網絡編程—異步加載(AsyncTask)

編輯:關於Android編程

看了前面的文章我們知道請求網絡的幾種方式:

1.使用TCP協議和URL進行網絡編程

    a)基於TCP協議:ServerSocket,Socket

    b)基於URL:URL    和    URLConnection

2.使用Http協議進行網絡編程

    a)HttpURLConnection

    b)HttpClient

我們知道這些網絡請求都應該在子線程中,不能在主線程中(因為耗時操作會阻塞主線程,造成ANR)。但是在子線程中請求的數據需要傳遞給主線程來更新UI。我們經常使用的一種方式應該是借助於 Handler機制

是的,這是一種方式,今天我們來講解另外一種方式來更新UI—–AsyncTask(異步加載).

這個AsyncTask(異步加載)將訪問網絡和更新UI放在了一起,其實究其根源也是使用了Handler機制,只不過幫我們把Handler機制和訪問網絡封裝起來罷了。

那這兩種方式做個比較:

Handler VS AsyncTask

AsyncTask實現的原理:AsyncTask的本質是一個線程池,所有提交的異步任務都會在這個線程池中的工作線程內執行,當工作線程需要跟UI線程交互時,工作線程會通過向在UI線程創建的Handler傳遞消息的方式,調用相關的回調函數,從而實現UI界面的更新。

優點:

①簡單快捷

②過程可控

缺點:

在使用多個異步操作和並需要進行Ui變更時,就變得復雜起來.

Handler實現的原理:在Handler 異步實現時,涉及到 Handler, Looper, Message,Thread四個對象,實現異步的流程是主線程啟動Thread(子線程)àthread(子線程)運行並生成Message- àLooper獲取Message並傳遞給HandleràHandler逐個獲取Looper中的Message,並進行UI變更。

優點:

①結構清晰,功能定義明確

②對於多個後台任務時,簡單清晰

缺點:

在單個後台異步處理時,顯得代碼過多,結構過於復雜(相對性)

既然這樣我們就來講下AsyncTask(異步加載)吧。

AsyncTask定義了三種泛型類型 Params,Progress和Result。(也是可以指定為空的,如 AsyncTask

 - Params 啟動任務執行的輸入參數。比如Http請求的URL

 - Progress 後台任務執行的進度百分比。

 - Result 後台執行任務最終返回的結果。比如String

使用過AsyncTask 的同學都知道一個異步加載數據最少要重寫以下這兩個方法:

doInBackground(Params…)

說明:

    doInBackground有返回值,並且返回值由Result決定

    參數列表首先是一個可變長參數,是由Params決定

    執行時機:在onPreExecute()方法之後立馬執行

    作用:主要負責執行那些很耗時的後台操作,在後台執行

    跟之前在子線程寫的代碼是一樣的

    在執行過程中可以調用publicProgress(Progress…)來更新任務的進度。

onPostExecute(Result)

說明:

    onPostExecute(Result)沒有返回值

    參數是doInBackground的返回值

    執行時機:doInBackground執行完

    相當於Handler 處理UI的方式

    此方法在主線程執行

有必要的話你還得重寫以下這三個方法,但不是必須的:

onProgressUpdate(Progress…)

說明:

    沒返回值,不會主動回調,而是需要publishProgress()去間接調用

    onProgressUpdate的參數由Progress決定

    執行時機:這個函數在doInBackground調用publishProgress()之後

    作用:在界面上展示任務的進度情況,可以使用進度條增加用戶體驗度

    跟之前handleMessesg中的代碼一樣

    此方法在主線程執行

onPreExecute()

說明:

    沒有返回值也沒有參數

    執行時機:這裡是最終用戶調用Excute時的接口,當任務執行之前開始調用此方法

    作用:可以在該方法中做一些准備工作及一些初始化的操作,這個方法可以不用實現
onCancelled() 用戶調用取消時,要做的操作

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

Task的實例必須在UI thread中創建

execute方法必須在UI thread中調用

不要手動的調用onPreExecute(), onPostExecute(Result),doInBackground(Params…), onProgressUpdate(Progress…)這幾個方法;

該task只能被執行一次,否則多次調用時將會出現異常

流程:

實例-excute(Params)-doInBackground的參數

Progress-publishProgress的參數-onProgressUpdate的參數

Result-doInBackground返回值-onPostExcute的參數

這裡舉個例子說明一下:

假設Params 為Integer
Progress 為Integer
Result 為String

則AsyncTask

示意圖:

這裡寫圖片描述

這幅圖可以知道各個方法的執行順序,以及各個參數的來源和流向。這應該很清楚了,我就不解釋了。

這裡寫個示例代碼模擬下:

效果:

這裡寫圖片描述

首先一個異步的下載的類DownloadTask.java

doInBackground中用個fZ喎?/kf/ware/vc/" target="_blank" class="keylink">vctGtu7fAtMSjxOK6xMqxstnX96GjPGJyIC8+DQqyzsr9tKvBy9K7uPbLr8Pfyv08L3A+DQo8cHJlIGNsYXNzPQ=="brush:java;"> /** * 流程: * 實例-excute(Params)-doInBackground的參數 * Progress-publishProgress的參數-onProgressUpdate的參數 * Result-doInBackground返回值-onPostExcute的參數 */ /** * 三個泛型 第一個參數Params:後台處理時需要傳遞過來的數據類型,比如URL ---String 第二個參數Progress:進度百分比 * 第三個參數Result:後台處理完成返回數據類型 * * @author Administrator * */ public class DownloadTask extends AsyncTask { TextView tv; ProgressBar pb; public DownloadTask(TextView tv, ProgressBar pb) { this.tv = tv; this.pb = pb; } // 執行時機:在執行實際的後台操作前,被UI線程調用 // 可以在該方法中做一些准備工作,這個方法可以不用實現 @Override protected void onPreExecute() { System.out.println("准備"); super.onPreExecute(); } // doInBackground有返回值,並且返回值由Result決定 // 參數列表首先是一個可變長參數,是由Params決定 // 執行時機:在onPreExecute()方法之後立馬執行 // 作用:主要負責執行那些很耗時的後台操作 // 跟之前在子線程寫的代碼是一樣的 @Override protected String doInBackground(Integer... params) { try { for (int i = 0; i < 101; i++) { Thread.sleep(params[0]); publishProgress(i); } } catch (InterruptedException e) { e.printStackTrace(); return "下載失敗"; } return "下載完成"; } // 沒返回值,不會主動回調,而是需要publishProgress()去間接調用 // onProgressUpdate的參數由Progress決定 // 執行時機:這個函數在doInBackground調用publishProgress()之後 // 作用:在界面上展示任務的進度情況 // 跟之前handleMessesg中的代碼一樣 @Override protected void onProgressUpdate(Integer... values) { tv.setText("當前下載了" + values[0] + "%"); pb.setProgress(values[0]); super.onProgressUpdate(values); } // 沒有返回值,參數是doInBackground的返回值 // 執行時機:doInBackground執行完 @Override protected void onPostExecute(String result) { tv.setText(result); super.onPostExecute(result); } }

activity_main.xml



    

MainActivity.java

public class MainActivity extends Activity {

    private ProgressBar pb;
    private TextView tv;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        pb = (ProgressBar) findViewById(R.id.pb);
        tv = (TextView) findViewById(R.id.tv);
    }
    public void onClick(View view) {
        DownloadTask downloadTask = new DownloadTask(tv, pb);
        downloadTask.execute(1000);
    }
}

看起來感覺很復雜,但是學會了用起來是很方便的。小伙伴趕緊試試吧。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved