AsyncTask是android提供的輕量級的異步類。比Handler更輕量級一些,適用於簡單的異步處理。android
AsyncTask內部封裝了Thread和Handler,簡化Thread+Handler,可讓咱們在後臺進行計算而且把計算的結果及時更新到UI上。併發
AsyncTask並非像多個線程那樣徹底並行執行的。異步
優勢:ide
簡單,快捷ui
過程可控url
結構清晰,功能定義明確spa
對於多個後臺任務時,簡單,清晰.net
缺點:線程
在使用多個異步操做和並須要進行Ui變動時,就變得複雜起來.設計
在單個後臺異步處理時,顯得代碼過多,結構過於複雜(相對性)
AsyncTask中維護着一個長度爲128的線程池,同時能夠執行5個工做線程,還有一個緩衝隊列,當線程池中已有128個線程,緩衝隊列已滿時,若是此時向線程提交任務,將會拋出RejectedExecutionException。
解決:由一個控制線程來處理AsyncTask的調用判斷線程池是否滿了,若是滿了則線程睡眠不然請求AsyncTask繼續處理。
AsyncTask直接繼承於Object類,位置爲android.os.AsyncTask。要使用AsyncTask工做咱們要提供三個泛型參數,並重載幾個方法(至少重載一個)。
AsyncTask定義了三種泛型類型 Params,Progress和Result。
Params 啓動任務執行的輸入參數,好比HTTP請求的URL。
Progress 後臺任務執行時,若是須要在界面上顯示當前的進度,則使用這裏指定的泛型做爲進度單位。
Result 後臺執行任務最終返回的結果,好比String。
doInBackground(Params…) 後臺執行,比較耗時的操做均可以放在這裏。注意這裏不能直接操做UI。此方法在後臺線程執行,完成任務的主要工做,一般須要較長的時間。在執行過程當中能夠調用publicProgress(Progress…)來更新任務的進度。
onPostExecute(Result) 至關於Handler 處理UI的方式,在這裏面可使用在doInBackground 獲得的結果處理操做UI。 此方法在主線程執行,任務執行的結果做爲此方法的參數返回
onProgressUpdate(Progress…) 可使用進度條增長用戶體驗度。 此方法在主線程執行,用於顯示任務執行的進度。當在後臺任務中調用了publishProgress(Progress...)方法後,這個方法就很快會被調用,方法中攜帶的參數就是在後臺任務中傳遞過來的。
onPreExecute() 這裏是最終用戶調用Excute時的接口,當任務執行以前開始調用此方法,能夠在這裏顯示進度對話框。
onCancelled() 用戶調用取消時,要作的操做
AsyncTask的類必須在UI線程加載(從4.1開始系統會幫咱們自動完成)
AsyncTask對象必須在UI線程建立
execute方法必須在UI線程調用
不要在你的程序中去直接調用onPreExecute(), onPostExecute, doInBackground, onProgressUpdate方法
一個AsyncTask對象只能執行一次,即只能調用一次execute方法,不然會報運行時異常
AsyncTask不是被設計爲處理耗時操做的,耗時上限爲幾秒鐘,若是要作長耗時操做,強烈建議你使用Executor,ThreadPoolExecutor以及FutureTask
在1.6以前,AsyncTask是串行執行任務的,1.6的時候AsyncTask開始採用線程池裏處理並行任務,可是從3.0開始,爲了不AsyncTask所帶來的併發錯誤,AsyncTask又採用一個線程來串行執行任務
public class DownloadFilesTask extends AsyncTask<URL, Integer, Long> { protected Long doInBackground(URL... urls) { int count = urls.length; long totalSize = 0; for (int i = 0; i < count; i++) { totalSize += Downloader.downloadFile(urls[i]); publishProgress((int) ((i / (float) count) * 100)); // Escape early if cancel() is called if (isCancelled()) break; } return totalSize; } protected void onProgressUpdate(Integer... progress) { setProgressPercent(progress[0]); } protected void onPostExecute(Long result) { showDialog("Downloaded " + result + " bytes"); } }
AsyncTask在4.1.1及是串行的,在2.3.3應該是並行的
@TargetApi(Build.VERSION_CODES.HONEYCOMB) @Override public void onClick(View v) { if (v == mButton) { new MyAsyncTask("AsyncTask#1").executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,""); new MyAsyncTask("AsyncTask#2").executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,""); new MyAsyncTask("AsyncTask#3").executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,""); new MyAsyncTask("AsyncTask#4").executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,""); new MyAsyncTask("AsyncTask#5").executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,""); } } private static class MyAsyncTask extends AsyncTask<String, Integer, String> { private String mName = "AsyncTask"; public MyAsyncTask(String name) { super(); mName = name; } @Override protected String doInBackground(String... params) { try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } return mName; } @Override protected void onPostExecute(String result) { super.onPostExecute(result); SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Log.e(TAG, result + "execute finish at " + df.format(new Date())); } }