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