asynctask和handler對比
1 ) asynctask實作的原理,和适用的優缺點
asynctask,是android提供的輕量級的異步類,可以直接繼承asynctask,在類中實作異步操作,并提供接口回報目前異步執行的程度(可以通過接口實作ui進度更新),最後回報執行的結果給ui主線程.
使用的優點:
l 簡單,快捷
l 過程可控
使用的缺點:
l 在使用多個異步操作和并需要進行ui變更時,就變得複雜起來.
2 )handler異步實作的原理和适用的優缺點
在handler 異步實作時,涉及到 handler, looper, message,thread四個對象,實作異步的流程是主線程啟動thread(子線程)àthread(子線程)運作并生成message-àlooper擷取message并傳遞給handleràhandler逐個擷取looper中的message,并進行ui變更。
使用的優點:
l 結構清晰,功能定義明确
l 對于多個背景任務時,簡單,清晰
使用的缺點:
l 在單個背景異步處理時,顯得代碼過多,結構過于複雜(相對性)
asynctask介紹
android的asynctask比handler更輕量級一些,适用于簡單的異步處理。
首先明确android之是以有handler和asynctask,都是為了不阻塞主線程(ui線程),且ui的更新隻能在主線程中完成,是以異步處理是不可避免的。
android為了降低這個開發難度,提供了asynctask。asynctask就是一個封裝過的背景任務類,顧名思義就是異步任務。
asynctask直接繼承于object類,位置為android.os.asynctask。要使用asynctask工作我們要提供三個泛型參數,并重載幾個方法(至少重載一個)。
asynctask定義了三種泛型類型 params,progress和result。
params 啟動任務執行的輸入參數,比如http請求的url。
progress 背景任務執行的百分比。
result 背景執行任務最終傳回的結果,比如string。
使用過asynctask 的同學都知道一個異步加載資料最少要重寫以下這兩個方法:
doinbackground(params…) 背景執行,比較耗時的操作都可以放在這裡。注意這裡不能直接操作ui。此方法在背景線程執行,完成任務的主要工作,通常需要較長的時間。在執行過程中可以調用publicprogress(progress…)來更新任務的進度。
onpostexecute(result) 相當于handler 處理ui的方式,在這裡面可以使用在doinbackground 得到的結果處理操作ui。 此方法在主線程執行,任務執行的結果作為此方法的參數傳回
有必要的話你還得重寫以下這三個方法,但不是必須的:
onprogressupdate(progress…) 可以使用進度條增加使用者體驗度。 此方法在主線程執行,用于顯示任務執行的進度。
onpreexecute() 這裡是最終使用者調用excute時的接口,當任務執行之前開始調用此方法,可以在這裡顯示進度對話框。
oncancelled() 使用者調用取消時,要做的操作
使用asynctask類,以下是幾條必須遵守的準則:
task的執行個體必須在ui thread中建立;
execute方法必須在ui thread中調用;
不要手動的調用onpreexecute(), onpostexecute(result),doinbackground(params...), onprogressupdate(progress...)這幾個方法;
該task隻能被執行一次,否則多次調用時将會出現異常;
一個超簡單的了解 asynctask 的例子:
main.xml
[java] view plaincopy
<?xml version="1.0" encoding="utf-8"?>
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<textview
android:id="@+id/textview01"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<progressbar
android:id="@+id/progressbar02"
style="?android:attr/progressbarstylehorizontal"
<button
android:id="@+id/button03"
android:text="更新progressbar"
</linearlayout>
mainactivity.java
[html] view plaincopy
package vic.wong.main;
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 button;
private progressbar progressbar;
private textview textview;
@override
public void oncreate(bundle savedinstancestate) {
super.oncreate(savedinstancestate);
setcontentview(r.layout.main);
button = (button)findviewbyid(r.id.button03);
progressbar = (progressbar)findviewbyid(r.id.progressbar02);
textview = (textview)findviewbyid(r.id.textview01);
button.setonclicklistener(new onclicklistener() {
@override
public void onclick(view v) {
progressbarasynctask asynctask = new progressbarasynctask(textview, progressbar);
asynctask.execute(1000);
}
});
}
}
netoperator.java
//模拟網絡環境
public class netoperator {
public void operator(){
try {
//休眠1秒
thread.sleep(1000);
} catch (interruptedexception e) {
// todo auto-generated catch block
e.printstacktrace();
}
progressbarasynctask .java
import android.os.asynctask;
/**
* 生成該類的對象,并調用execute方法之後
* 首先執行的是onproexecute方法
* 其次執行doinbackgroup方法
*
*/
public class progressbarasynctask extends asynctask<integer, integer, string> {
public progressbarasynctask(textview textview, progressbar progressbar) {
super();
this.textview = textview;
this.progressbar = progressbar;
/**
* 這裡的integer參數對應asynctask中的第一個參數
* 這裡的string傳回值對應asynctask的第三個參數
* 該方法并不運作在ui線程當中,主要用于異步操作,所有在該方法中不能對ui當中的空間進行設定和修改
* 但是可以調用publishprogress方法觸發onprogressupdate對ui進行操作
*/
protected string doinbackground(integer... params) {
netoperator netoperator = new netoperator();
int i = 0;
for (i = 10; i <= 100; i+=10) {
netoperator.operator();
publishprogress(i);
return i + params[0].intvalue() + "";
* 這裡的string參數對應asynctask中的第三個參數(也就是接收doinbackground的傳回值)
* 在doinbackground方法執行結束之後在運作,并且運作在ui線程當中 可以對ui空間進行設定
protected void onpostexecute(string result) {
textview.settext("異步操作執行結束" + result);
//該方法運作在ui線程當中,并且運作在ui線程當中 可以對ui空間進行設定
protected void onpreexecute() {
textview.settext("開始執行異步線程");
* 這裡的intege參數對應asynctask中的第二個參數
* 在doinbackground方法當中,,每次調用publishprogress方法都會觸發onprogressupdate執行
* onprogressupdate是在ui線程中執行,所有可以對ui空間進行操作
protected void onprogressupdate(integer... values) {
int vlaue = values[0];
progressbar.setprogress(vlaue);
}