介紹
AsyncTask是一個輕量級的異步任務類癣漆,它可以在線程池中執(zhí)行任務,然后把結果和執(zhí)行進度傳遞到主線程并在主線程更新UI剂买。內部實現封裝了Thread和Handler惠爽,可以方便的執(zhí)行后臺任務以及主線程中訪問UI,但是AsyncTask并不適合執(zhí)行特別耗時的操作瞬哼,耗時操作建議使用線程池婚肆。
核心方法
AsyncTask是一個抽象的泛型類提供了三個泛型參數<Params,Progress,Result>,Params表示參數的類型坐慰,Progress表示運行的進度较性,Result表示運行結束后返回的結果類型。
主要提供可以下四個核心方法:
1.onPreExecute()结胀,在主線程中執(zhí)行,在異步任務以前,主要做一些準備工作
2.doInBackground(Params... params)赞咙,在線程池中工作,params是傳遞進來的參數,在這個方法中可以通過publicProgress方法來更新進度糟港,public會調用onProgressUpdate方法來更新進度攀操。這個方法需要返回計算結果返回給onPostExecute方法
3.onProgressUpdate(Progress progress),這個方法運行在UI線程中秸抚,用來更新進度
4.onPostExecute(Result result)速和,運行在主線程中歹垫,doInBackground運行完成后會調用此方法,result既是是doInBackground返回的結果
使用方式和注意
1.一個asynctask對象只能執(zhí)行一次颠放,如果多次調用一個對象會報 Cannot execute task: the task is already running.異常
2.使用execute()運行AsyncTask县钥,3.0(API 11)以后默認是串行執(zhí)行任務。也可以通過executeOnExecutor方法并行執(zhí)行任務慈迈,可以根據不同需求傳遞通過executeOnExecutor(Executor exec,Params... params)構造方法傳遞一個Executor 設置線程池并行的數量,如下圖:設置固定5個線程的線程池省有,只有前5個任務執(zhí)行完畢后痒留,最后兩個線程才會執(zhí)行
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_asynctask);
newFixedExecutor = Executors.newFixedThreadPool(5);//設置固定5個線程的線程池
myAsyncTask =new MyAsyncTask();
myAsyncTask2 =new MyAsyncTask();
myAsyncTask3 =new MyAsyncTask();
myAsyncTask4 =new MyAsyncTask();
myAsyncTask5 =new MyAsyncTask();
myAsyncTask6 =new MyAsyncTask();
myAsyncTask7 =new MyAsyncTask();
}
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
myAsyncTask.executeOnExecutor(newFixedExecutor ,mProgressBar);
myAsyncTask2.executeOnExecutor(newFixedExecutor ,mProgressBar2);
myAsyncTask3.executeOnExecutor(newFixedExecutor ,mProgressBar3);
myAsyncTask4.executeOnExecutor(newFixedExecutor ,mProgressBar4);
myAsyncTask5.executeOnExecutor(newFixedExecutor ,mProgressBar5);
myAsyncTask6.executeOnExecutor(newFixedExecutor ,mProgressBar6);
myAsyncTask7.executeOnExecutor(newFixedExecutor ,mProgressBar7);
}
});
3.AsyncTask不適合執(zhí)行特別耗時的操作,耗時操作建議使用線程池來完成
4.AsyncTask一般都說只能在主線程中調用蠢沿,但是在API 26下伸头,看AsyncTask源碼其實也可以在子線程中調用,因為在初始化Handler時已經將主線程的Looper傳遞Handler(如下圖代碼)舷蟀,這樣消息仍然可以傳遞給主線程恤磷。其他以前版本源碼沒有看過,但是能不能在其他線程中運行野宜,就看源碼中是否傳遞的Looper是當前線程的還是getMainLooper()扫步,如果是getMainLooper,那么在其他線程運行應該就沒問題匈子。
private static Handler getMainHandler() {
synchronized (AsyncTask.class) {
if (sHandler == null) {
sHandler = new InternalHandler(Looper.getMainLooper());
}
return sHandler;
}
}
AsyncTask版本演進
1.在1.6之前河胎,AsyncTask是串行執(zhí)行任務
2.在1.6的時候,AsyncTask開始采用線程池處理并行任務
3.但是從3.0開始為了避免AsyncTask所帶來的并發(fā)錯誤虎敦,AsyncTask又采用一個線程來串行執(zhí)行任務游岳,但是仍然可以通過executeOnExecutor方法來并行執(zhí)行任務
參考
1.《Android開發(fā)藝術開發(fā)探索》任玉剛