AsyncTask,是android提供的輕量級的異步類,能夠直接繼承AsyncTask,在類中實現異步操做,並提供接口反饋當前異步執行的程度(能夠經過接口實現UI進度更新),最後反饋執行的結果給UI主線程.php
使用的優勢:html
l 簡單,快捷java
l 過程可控android
使用的缺點:算法
l 在使用多個異步操做和並須要進行Ui變動時,就變得複雜起來.數據庫
2 Handler異步實現的原理和適用的優缺點編程
在Handler 異步實現時,涉及到 Handler, Looper, Message,Thread四個對象,實現異步的流程是主線程啓動Thread(子線程)àthread(子線程)運行並生成Message- àLooper獲取Message並傳遞給HandleràHandler逐個獲取Looper中的Message,並進行UI變動。緩存
使用的優勢:安全
l 結構清晰,功能定義明確網絡
l 對於多個後臺任務時,簡單,清晰
AsyncTask這個類感受使用比較簡單,就是實現其中幾個方法,onPreExecute()方法是在任務剛開始運行時執行的一些初始化操做,好比初 始化一個進度條等等,而後就執行doInBackground()方法這裏面主要放業務操做,好比查詢數據庫等,在這個方法執行的時候會調用 onProgressUpdate(),能夠在這個方法中更新UI界面,最後是調用onPostExecute()方法,當獲得業務結果後就能夠在這個方 法中返回給UI線程,也能夠關閉一些執行這個業務時開的一些資源。你們能夠看得出AsyncTask這個類是一個泛型類,這個類的三個參數以此對應 doInBackground(String... params),onProgressUpdate(String... values),onPostExecute(String result)的參數,很形象的···若是不須要傳參和返回值,能夠用Void代替。而doInBackground(String... params)方法的返回值也就是onPostExecute(String result)方法的參數值,由於doInBackground方法執行後返回的值是在onPostExecute(String result)中處理的。
用handler方式處理須要知道與handler相關的幾個組件,Looper和Queue,其實Looper的做用就是把handler發送的消息放 到Queue中,並把消息廣播給全部與這個Queue相關的handler,而Queue通常是主線程開啓的時候就給這個線程分配了一個,因此你要與UI 主線程通訊必須用於這個Queue相關聯的handler對象才行,通常handler對象在那個線程中建立的就與那個線程的queue關聯,因此在UI 線程中建立的handler對象就與UI線程通信,這樣咱們就能夠在子線程中發送消息給主線程,實現更新UI的功能。那主線程又是怎麼處理子線程發送的消 息的呢?其實在生成handler對象的時候咱們就要實現handler對象的handleMessage()方法這個方法就是主線程接受並處理子線程發 送過來的消息的方法,從而實現 更新UI線程的功能。
不少網友可能發現Android平臺不少應用使用的都是AsyncTask,而並不是Thread和Handler去更新UI,這裏給你們說下他們到底有什 麼區別,咱們平時應該使用哪一種解決方案。從Android 1.5開始系統將AsyncTask引入到android.os包中,過去在很早1.1和1.0 SDK時其實官方將其命名爲UserTask,其內部是JDK 1.5開始新增的concurrent庫,作過J2EE的網友可能明白併發庫效率和強大性,比Java原始的Thread更靈活和強大,但對於輕量級的使 用更爲佔用系統資源。Thread是Java早期爲實現多線程而設計的,比較簡單不支持concurrent中不少特性在同步和線程池類中須要本身去實現 不少的東西,對於分佈式應用來講更須要本身寫調度代碼,而爲了Android UI的刷新Google引入了Handler和Looper機制,它們均基於消息實現,有時可能消息隊列阻塞或其餘緣由沒法準確的使用。
推薦你們使用AsyncTask代替Thread+Handler的方式,不只調用上更爲簡單,通過實測更可靠一些,Google在Browser中大量 使用了異步任務做爲處理耗時的I/O操做,好比下載文件、讀寫數據庫等等,它們在本質上都離不開消息,可是AsyncTask相比Thread加 Handler更爲可靠,更易於維護,但AsyncTask缺點也是有的好比一旦線程開啓即dobackground方法執行後沒法給線程發送消息,僅能 經過預先設置好的標記來控制邏輯,固然能夠經過線程的掛起等待標誌位的改變來通信,對於某些應用Thread和Handler以及Looper可能更靈 活。
本文主要講解下AsyncTask的使用以及Handler的應用
首先,咱們得明確下一個概念,什麼是UI線程。顧名思義,ui線程就是管理着用戶界面的那個線程!
android的ui線程操做並非安全的,而且和用戶直接進行界面交互的操做都必須在ui線程中進行才能夠。這種模式叫作單線程模式。
咱們在單線程模式下編程必定要注意:不要阻塞ui線程、確保只在ui線程中訪問ui組件
當咱們要執行一個複雜耗時的算法而且最終要將計算結果反映到ui上時,咱們會發現,咱們根本沒辦法同時保證上面的兩點要求;咱們確定會想到開啓一個新的線程,讓這個複雜耗時的任務到後臺去執行,可是執行完畢了呢?咱們發現,咱們沒法再與ui進行交互了。
爲了解決這種狀況,android爲咱們提供了不少辦法。
1)、handler和message機制:經過顯示的拋出、捕獲消息與ui進行交互;
2)、Activity.runOnUiThread(Runnable):若是當前線程爲ui線程,則當即執行;不然,將參數中的線程操做放入到ui線程的事件隊列中,等待執行。
3)、View.post(Runnable):將操做放入到message隊列中,若是放入成功,該操做將會在ui線程中執行,並返回true,不然返回false
4)、View.postDelayed(Runnable, long)跟第三條基本同樣,只不過添加了一個延遲時間。
5)、android1.5之後爲咱們提供了一個工具類來搞定這個問題AsyncTask.
AsyncTask是抽象類,定義了三種泛型類型 Params,Progress,Result。
Params 啓動任務執行的輸入參數,好比HTTP請求的URL
Progress 後臺任務執行的百分比。
Result 後臺執行任務最終返回的結果,好比String
用程序調用,開發者須要作的就是實現這些方法。
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只能被執行一次,不然屢次調用時將會出現異常
下面介紹最本質的多線程:hanlder和message機制:
爲什麼須要多線程:
在平常應用中,咱們一般須要處理一些「後臺,用戶不可見」的操做,例如說,咱們須要下載一個音樂,要是你的應用必須等用戶下載完成以後才能夠進行別的操 做,那確定讓用戶很是的不爽。這時候,咱們一般的作法是,讓這些操做去後臺執行,而後等後臺執行完畢以後,再給用戶彈出相應的提示信息。這時候,咱們就需 要使用多線程機制,而後經過建立一個新的線程來執行這些操做。
明白了,實現需求,咱們就準備着手實現了。可是,通過進一步的瞭解,咱們悲劇的發現,android中的線程機制是,只能在UI線程中和用戶進行交互。當 咱們建立了一個新線程,執行了一些後臺操做,執行完成以後,咱們想要給用戶彈出對話框以確認,可是卻悲劇的發現,咱們根本沒法返回UI主線程了。
(說明:何爲UI線程:UI線程就是你當前看到的這些交互界面所屬的線程)。
這時候,咱們若是想要實現這些功能,咱們就須要一個android爲咱們提供的handler和message機制。
先講解下編程機制:
咱們一般在UI線程中建立一個handler,handler至關於一個處理器,它主要負責處理和綁定到該handler的線程中的message。每一 個handler都必須關聯一個looper,而且二者是一一對應的,注意,這點很重要哦!此外,looper負責從其內部的messageQueue中 拿出一個個的message給handler進行處理。由於咱們這裏handler是在UI線程中實現的,因此通過這麼一個handler、 message機制,咱們就能夠回到UI線程中了。
何爲handler:處理後臺進程返回數據的工做人員。
何爲message:後臺進程返回的數據,裏面能夠存儲bundle等數據格式
何爲messageQueue:是線程對應looper的一部分,負責存儲從後臺進程中拋回的和當前handler綁定的message,是一個隊列。
何爲looper:looper至關於一個messageQueue的管理人員,它會不停的循環的遍歷隊列,而後將符合條件的message一個個的拿出來交給handler進行處理。
注意,handler是在UI線程中聲明的,若是咱們直接用相似代碼執行一個線程的話,實際上並無建立一個新的線程,由於handler已經跟默認的UI線程中的looper綁定了。
若是有興趣的話,能夠去看下Handler的默認空構造函數便知道緣由了,裏面直接綁定了當前UI線程的looper。
下面給出一個比較簡單,而且實用的實例。
這2種方式均可以實現,可是他們的區別在哪裏?優缺點各是什麼?
(1)、AsyncTask是封裝好的線程池,比起Thread+Handler的方式,AsyncTask在操做UI線程上更方便,由於onPreExecute()、onPostExecute()及更新UI方法onProgressUpdate()均運行在主線程中,這樣就不用Handler發消息處理了;
(2)、我不太贊成封裝好就會影響性能的說法,在我實際的運用中,真正的缺點來自於AsyncTask的全局線程池只有5個工做線程,也就是說,一個APP若是運用AsyncTask技術來執行線程,那麼同一時間最多隻能有5個線程同時運行,其餘線程將被阻塞(注:不運用AsyncTask執行的線程,也就是本身new出來的線程不受此限制),因此AsyncTask不要用於多線程取網絡數據,由於極可能這樣會產生阻塞,從而下降效率。
三. 可否同時併發100+asynctask呢?
AsyncTask用的是線程池機制,容量是128,最多同時運行5個core線程,剩下的排隊。
public class MainService extends Service{ private static Task task;//當前執行任務 private static Map<String, Activity> allActivitys = new HashMap<String, Activity>();//緩存activity集合 private static ExecutorService exec = Executors.newSingleThreadExecutor(); @Override public void onStart(Intent intent, int startId) { super.onStart(intent, startId); MainAsyncTask asyncTask = new MainAsyncTask(); //asyncTask.execute(task); //asyncTask.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, task); //asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, task); //asyncTask.executeOnExecutor(Executors.newFixedThreadPool(2), task); asyncTask.executeOnExecutor(exec, task); } private final class MainAsyncTask extends AsyncTask<Object, Integer, Object>{ private Task task; @Override protected Object doInBackground(Object... params) { Object result = null; task = (Task)params[0]; switch (task.getTaskID()) { case Task.TASK_USER_LOGIN: try { Thread.sleep(3000); System.out.println("任務"+task.getTaskID()+" Thread id: "+Thread.currentThread().getId()); } catch (InterruptedException e) { e.printStackTrace(); } break; case 2: System.out.println("任務"+task.getTaskID()+" Thread id: "+Thread.currentThread().getId()); break; } return result; } @Override protected void onPostExecute(Object result) { super.onPostExecute(result); ActivityInterFace aif; switch (task.getTaskID()) { case Task.TASK_USER_LOGIN: aif = (ActivityInterFace)allActivitys.get("LoginActivity"); aif.refresh(1, result); break; case 2: aif = (ActivityInterFace)allActivitys.get("LoginActivity"); aif.refresh(2, result); break; default: break; } } } /** * 添加新任務 * @param task */ public static void addTask(Context context, Task task) { MainService.task = task; context.startService(new Intent("mainService")); } /** * 緩存activity * @param activity */ public static void addActivity(Activity activity) { String path = activity.getClass().getName(); String name = path.substring(path.lastIndexOf(".")+1); allActivitys.put(name, activity); } @Override public IBinder onBind(Intent intent) { return null; } }
當我執行兩次調用asyncTask.execute(task);時發現只有當第一次的任務完成後才執行下一下任務!!怎麼回事?
AyncTask不是號稱異步線程池嗎?既然是線程池那麼多任務執行時應該能夠併發執行啊,至少兩個任務能夠併發執
行,之前看過一個視頻,人家的就能夠啊!糾結了一下午,經過查閱資料和本身的動手實驗終於把問題搞明白了。
原來在SDK3.0之前的版本執行asyncTask.execute(task);時的確是多線程併發執行的,線程池大小爲5,最大可大
128個,google在3.0之後的版本中作了修改,將asyncTask.execute(task);修改成了順序執行,即只有當一個的實例
的任務完成後在執行下一個實例的任務。
那麼怎麼才能併發執行呢,很簡單,3.0後新增了一個方法executeOnExecutor(Executor
exec, Object... params),
該方法接受2個參數,第一個是Executor,第二個是任務參數。第一個是線程池實例,google爲咱們預約義了兩種:
第一種是AsyncTask.SERIAL_EXECUTOR,第二種是AsyncTask.THREAD_POOL_EXECUTOR,顧名思義,第一
種其實就像3.0之後的execute方法,是順序執行的。第二種就是3.0之前的execute方法,是能夠併發執行的。咱們直
接用asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, task);就能夠多任務併發執行了。
既然executeOnExecutor第一個參數是Executor,那麼咱們能夠自定義Executor嗎?固然能夠,Executor主要由四
種類型newCachedThreadPool,newFixedThreadPool,newScheduledThreadPool,newSingleThreadExecutor
(具體使用解析能夠看我上一篇文章點擊打開連接),但是當我這樣使用
asyncTask.executeOnExecutor(Executors.newFixedThreadPool(1), task);或者
asyncTask.executeOnExecutor(Executors.newSingleThreadExecutor, task);並無像我想象的與
asyncTask.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, task);那樣是單線程順序執行,而是像
asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, task);是多線程併發執行的,我不是
已經規定newFixedThreadPool的線程池數量是1或者是newSingleThreadExecutor單線程了麼!怎麼回事呢?原來程
序在每次調用asyncTask.executeOnExecutor(Executors.newFixedThreadPool(2), task)時會獲取一個新的Executor對
象,這個對象內的線程只執行對應的task,因此不管哪一種狀況每一個task都有一個新的線程來執行,即併發執行。
知道緣由就好辦了,咱們定義個一全局靜態變量
private static ExecutorService exec = Executors.newSingleThreadExecutor();程序在每次調用
asyncTask.executeOnExecutor(exec, task);時是使用的同一個Executor,執行效果以下:
當Executor類型爲:private static ExecutorService exec = Executors.newFixedThreadPool(2);只有兩個線程在執行
任務
當Executor類型爲:private static ExecutorService exec = Executors.newSingleThreadExecutor();只有一個線程在執行任務
package com.example.ztestandroid; import java.util.Calendar; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import android.app.Activity; import android.os.AsyncTask; import android.os.Bundle; import com.example.ztestandroid.bean.Task; public class MainActivity extends Activity { private static ExecutorService exec = Executors.newSingleThreadExecutor(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); System.out.println("start time: "+Calendar.SECOND); for (int i = 1; i < 10; i++) { int count = i%2==0?1:2; Task task = new Task(count, "task "+i); MainAsyncTask asyncTask = new MainAsyncTask(); /* * 順序執行,AsyncTask裏面有5個核心線程,最大128個 * 01-14 11:30:47.000: I/System.out(17418): start time: 13 01-14 11:30:47.000: I/System.out(17418): end time: 13 01-14 11:30:47.000: I/System.out(17418): 任務2 task 1 Thread id: 840 seconds: 1421206247008 01-14 11:30:50.020: I/System.out(17418): 任務1 task 2 Thread id: 841 seconds: 1421206250028 01-14 11:30:50.025: I/System.out(17418): 任務2 task 3 Thread id: 842 seconds: 1421206250033 01-14 11:30:53.030: I/System.out(17418): 任務1 task 4 Thread id: 843 seconds: 1421206253037 01-14 11:30:53.040: I/System.out(17418): 任務2 task 5 Thread id: 844 seconds: 1421206253047 01-14 11:30:56.050: I/System.out(17418): 任務1 task 6 Thread id: 844 seconds: 1421206256053 01-14 11:30:56.050: I/System.out(17418): 任務2 task 7 Thread id: 844 seconds: 1421206256055 01-14 11:30:59.050: I/System.out(17418): 任務1 task 8 Thread id: 844 seconds: 1421206259057 01-14 11:30:59.050: I/System.out(17418): 任務2 task 9 Thread id: 844 seconds: 1421206259058 */ // asyncTask.execute(task); // 和asyncTask.execute(task)執行結果相同,順序執行。 // asyncTask.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, task); /* * 能夠看出是異步執行,線程池裏面最多有5個線程 * 01-14 11:43:14.115: I/System.out(18208): start time: 13 01-14 11:43:14.115: I/System.out(18208): end time: 13 01-14 11:43:14.115: I/System.out(18208): 任務2 task 1 Thread id: 880 seconds: 1421206994121 01-14 11:43:14.115: I/System.out(18208): 任務2 task 3 Thread id: 877 seconds: 1421206994122 01-14 11:43:14.115: I/System.out(18208): 任務2 task 5 Thread id: 876 seconds: 1421206994122 01-14 11:43:14.115: I/System.out(18208): 任務2 task 7 Thread id: 877 seconds: 1421206994123 01-14 11:43:14.115: I/System.out(18208): 任務2 task 9 Thread id: 877 seconds: 1421206994123 01-14 11:43:17.115: I/System.out(18208): 任務1 task 2 Thread id: 880 seconds: 1421206997122 01-14 11:43:17.115: I/System.out(18208): 任務1 task 6 Thread id: 878 seconds: 1421206997123 01-14 11:43:17.115: I/System.out(18208): 任務1 task 8 Thread id: 876 seconds: 1421206997123 01-14 11:43:17.115: I/System.out(18208): 任務1 task 4 Thread id: 879 seconds: 1421206997123 */ asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, task); /* * 異步執行 * 01-14 11:28:06.915: I/System.out(17143): start time: 13 01-14 11:28:06.915: I/System.out(17143): 任務2 task 1 Thread id: 837 seconds: 1421206086924 01-14 11:28:06.920: I/System.out(17143): 任務2 task 3 Thread id: 839 seconds: 1421206086925 01-14 11:28:06.920: I/System.out(17143): 任務2 task 5 Thread id: 841 seconds: 1421206086926 01-14 11:28:06.920: I/System.out(17143): 任務2 task 7 Thread id: 843 seconds: 1421206086926 01-14 11:28:06.920: I/System.out(17143): end time: 13 01-14 11:28:06.920: I/System.out(17143): 任務2 task 9 Thread id: 845 seconds: 1421206086927 01-14 11:28:09.925: I/System.out(17143): 任務1 task 2 Thread id: 838 seconds: 1421206089926 01-14 11:28:09.925: I/System.out(17143): 任務1 task 4 Thread id: 840 seconds: 1421206089927 01-14 11:28:09.925: I/System.out(17143): 任務1 task 6 Thread id: 842 seconds: 1421206089927 01-14 11:28:09.925: I/System.out(17143): 任務1 task 8 Thread id: 844 seconds: 1421206089927 */ // asyncTask.executeOnExecutor(Executors.newFixedThreadPool(2), task); /* * 執行結果: * 任務1 task 2 Thread id: 816 seconds: 1421205791881 任務2 task 3 Thread id: 816 seconds: 1421205791882 任務1 task 4 Thread id: 816 seconds: 1421205794883 任務2 task 5 Thread id: 816 seconds: 1421205794883 任務1 task 6 Thread id: 816 seconds: 1421205797884 任務2 task 7 Thread id: 816 seconds: 1421205797885 任務1 task 8 Thread id: 816 seconds: 1421205800886 任務2 task 9 Thread id: 816 seconds: 1421205800887 */ // asyncTask.executeOnExecutor(exec, task); } System.out.println("end time: "+Calendar.SECOND); } private final class MainAsyncTask extends AsyncTask<Object, Integer, Object>{ private Task task; @Override protected Object doInBackground(Object... params) { Object result = null; task = (Task)params[0]; switch (task.getTaskID()) { case Task.TASK_USER_LOGIN: try { Thread.sleep(3000); System.out.println("任務"+task.getTaskID()+" "+ task.getTask()+" Thread id: "+Thread.currentThread().getId()+" seconds: "+System.currentTimeMillis()); } catch (InterruptedException e) { e.printStackTrace(); } break; case 2: System.out.println("任務"+task.getTaskID()+" "+ task.getTask()+" Thread id: "+Thread.currentThread().getId()+" seconds: "+System.currentTimeMillis()); break; } return result; } @Override protected void onPostExecute(Object result) { super.onPostExecute(result); } } }
public abstract class AsyncTask { private static final String LOG_TAG = AsyncTask; //獲取當前的cpu核心數 private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors(); //線程池核心容量 private static final int CORE_POOL_SIZE = CPU_COUNT + 1; //線程池最大容量 private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1; //過剩的空閒線程的存活時間 private static final int KEEP_ALIVE = 1; //ThreadFactory 線程工廠,經過工廠方法newThread來獲取新線程 private static final ThreadFactory sThreadFactory = new ThreadFactory() { //原子整數,能夠在超高併發下正常工做 private final AtomicInteger mCount = new AtomicInteger(1); public Thread newThread(Runnable r) { return new Thread(r, AsyncTask # + mCount.getAndIncrement()); } }; //靜態阻塞式隊列,用來存放待執行的任務,初始容量:128個 private static final BlockingQueue sPoolWorkQueue = new LinkedBlockingQueue(128); /** * 靜態併發線程池,能夠用來並行執行任務,儘管從3.0開始,AsyncTask默認是串行執行任務 * 可是咱們仍然能構造出並行的AsyncTask */ public static final Executor THREAD_POOL_EXECUTOR = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory); /** * 靜態串行任務執行器,其內部實現了串行控制, * 循環的取出一個個任務交給上述的併發線程池去執行 */ public static final Executor SERIAL_EXECUTOR = new SerialExecutor(); //消息類型:發送結果 private static final int MESSAGE_POST_RESULT = 0x1; //消息類型:更新進度 private static final int MESSAGE_POST_PROGRESS = 0x2; /**靜態Handler,用來發送上述兩種通知,採用UI線程的Looper來處理消息 * 這就是爲何AsyncTask必須在UI線程調用,由於子線程 * 默認沒有Looper沒法建立下面的Handler,程序會直接Crash */ private static final InternalHandler sHandler = new InternalHandler(); //默認任務執行器,被賦值爲串行任務執行器,就是它,AsyncTask變成串行的了 private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR; //以下兩個變量咱們先不要深究,不影響咱們對總體邏輯的理解 private final WorkerRunnable mWorker; private final FutureTask mFuture; //任務的狀態 默認爲掛起,即等待執行,其類型標識爲易變的(volatile) private volatile Status mStatus = Status.PENDING; //原子布爾型,支持高併發訪問,標識任務是否被取消 private final AtomicBoolean mCancelled = new AtomicBoolean(); //原子布爾型,支持高併發訪問,標識任務是否被執行過 private final AtomicBoolean mTaskInvoked = new AtomicBoolean(); /*串行執行器的實現,咱們要好好看看,它是怎麼把並行轉爲串行的 *目前咱們須要知道,asyncTask.execute(Params ...)實際上會調用 *SerialExecutor的execute方法,這一點後面再說明。也就是說:當你的asyncTask執行的時候, *首先你的task會被加入到任務隊列,而後排隊,一個個執行 */ private static class SerialExecutor implements Executor { //線性雙向隊列,用來存儲全部的AsyncTask任務 final ArrayDeque mTasks = new ArrayDeque(); //當前正在執行的AsyncTask任務 Runnable mActive; public synchronized void execute(final Runnable r) { //將新的AsyncTask任務加入到雙向隊列中 mTasks.offer(new Runnable() { public void run() { try { //執行AsyncTask任務 r.run(); } finally { //當前AsyncTask任務執行完畢後,進行下一輪執行,若是還有未執行任務的話 //這一點很明顯體現了AsyncTask是串行執行任務的,老是一個任務執行完畢纔會執行下一個任務 scheduleNext(); } } }); //若是當前沒有任務在執行,直接進入執行邏輯 if (mActive == null) { scheduleNext(); } } protected synchronized void scheduleNext() { //從任務隊列中取出隊列頭部的任務,若是有就交給併發線程池去執行 if ((mActive = mTasks.poll()) != null) { THREAD_POOL_EXECUTOR.execute(mActive); } } } /** * 任務的三種狀態 */ public enum Status { /** * 任務等待執行 */ PENDING, /** * 任務正在執行 */ RUNNING, /** * 任務已經執行結束 */ FINISHED, } /** 隱藏API:在UI線程中調用,用來初始化Handler */ public static void init() { sHandler.getLooper(); } /** 隱藏API:爲AsyncTask設置默認執行器 */ public static void setDefaultExecutor(Executor exec) { sDefaultExecutor = exec; } /** * Creates a new asynchronous task. This constructor must be invoked on the UI thread. */ public AsyncTask() { mWorker = new WorkerRunnable() { public Result call() throws Exception { mTaskInvoked.set(true); Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); //noinspection unchecked return postResult(doInBackground(mParams)); } }; mFuture = new FutureTask(mWorker) { @Override protected void done() { try { postResultIfNotInvoked(get()); } catch (InterruptedException e) { android.util.Log.w(LOG_TAG, e); } catch (ExecutionException e) { throw new RuntimeException(An error occured while executing doInBackground(), e.getCause()); } catch (CancellationException e) { postResultIfNotInvoked(null); } } }; } private void postResultIfNotInvoked(Result result) { final boolean wasTaskInvoked = mTaskInvoked.get(); if (!wasTaskInvoked) { postResult(result); } } //doInBackground執行完畢,發送消息 private Result postResult(Result result) { @SuppressWarnings(unchecked) Message message = sHandler.obtainMessage(MESSAGE_POST_RESULT, new AsyncTaskResult(this, result)); message.sendToTarget(); return result; } /** * 返回任務的狀態 */ public final Status getStatus() { return mStatus; } /** * 這個方法是咱們必需要重寫的,用來作後臺計算 * 所在線程:後臺線程 */ protected abstract Result doInBackground(Params... params); /** * 在doInBackground以前調用,用來作初始化工做 * 所在線程:UI線程 */ protected void onPreExecute() { } /** * 在doInBackground以後調用,用來接受後臺計算結果更新UI * 所在線程:UI線程 */ protected void onPostExecute(Result result) { } /** * Runs on the UI thread after {@link #publishProgress} is invoked. /** * 在publishProgress以後調用,用來更新計算進度 * 所在線程:UI線程 */ protected void onProgressUpdate(Progress... values) { } /** * cancel被調用而且doInBackground執行結束,會調用onCancelled,表示任務被取消 * 這個時候onPostExecute不會再被調用,兩者是互斥的,分別表示任務取消和任務執行完成 * 所在線程:UI線程 */ @SuppressWarnings({UnusedParameters}) protected void onCancelled(Result result) { onCancelled(); } protected void onCancelled() { } public final boolean isCancelled() { return mCancelled.get(); } public final boolean cancel(boolean mayInterruptIfRunning) { mCancelled.set(true); return mFuture.cancel(mayInterruptIfRunning); } public final Result get() throws InterruptedException, ExecutionException { return mFuture.get(); } public final Result get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { return mFuture.get(timeout, unit); } /** * 這個方法如何執行和系統版本有關,在AsyncTask的使用規則裏已經說明,若是你真的想使用並行AsyncTask, * 也是能夠的,只要稍做修改 * 必須在UI線程調用此方法 */ public final AsyncTask execute(Params... params) { //串行執行 return executeOnExecutor(sDefaultExecutor, params); //若是咱們想並行執行,這樣改就好了,固然這個方法咱們無法改 //return executeOnExecutor(THREAD_POOL_EXECUTOR, params); } /** * 經過這個方法咱們能夠自定義AsyncTask的執行方式,串行or並行,甚至能夠採用本身的Executor * 爲了實現並行,咱們能夠在外部這麼用AsyncTask: * asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, Params... params); * 必須在UI線程調用此方法 */ public final AsyncTask executeOnExecutor(Executor exec, Params... params) { if (mStatus != Status.PENDING) { switch (mStatus) { case RUNNING: throw new IllegalStateException(Cannot execute task: + the task is already running.); case FINISHED: throw new IllegalStateException(Cannot execute task: + the task has already been executed + (a task can be executed only once)); } } mStatus = Status.RUNNING; //這裏#onPreExecute會最早執行 onPreExecute(); mWorker.mParams = params; //而後後臺計算#doInBackground才真正開始 exec.execute(mFuture); //接着會有#onProgressUpdate被調用,最後是#onPostExecute return this; } /** * 這是AsyncTask提供的一個靜態方法,方便咱們直接執行一個runnable */ public static void execute(Runnable runnable) { sDefaultExecutor.execute(runnable); } /** * 打印後臺計算進度,onProgressUpdate會被調用 */ protected final void publishProgress(Progress... values) { if (!isCancelled()) { sHandler.obtainMessage(MESSAGE_POST_PROGRESS, new AsyncTaskResult(this, values)).sendToTarget(); } } //任務結束的時候會進行判斷,若是任務沒有被取消,則onPostExecute會被調用 private void finish(Result result) { if (isCancelled()) { onCancelled(result); } else { onPostExecute(result); } mStatus = Status.FINISHED; } //AsyncTask內部Handler,用來發送後臺計算進度更新消息和計算完成消息 private static class InternalHandler extends Handler { @SuppressWarnings({unchecked, RawUseOfParameterizedType}) @Override public void handleMessage(Message msg) { AsyncTaskResult result = (AsyncTaskResult) msg.obj; switch (msg.what) { case MESSAGE_POST_RESULT: // There is only one result result.mTask.finish(result.mData[0]); break; case MESSAGE_POST_PROGRESS: result.mTask.onProgressUpdate(result.mData); break; } } } private static abstract class WorkerRunnable implements Callable { Params[] mParams; } @SuppressWarnings({RawUseOfParameterizedType}) private static class AsyncTaskResult { final AsyncTask mTask; final Data[] mData; AsyncTaskResult(AsyncTask task, Data... data) { mTask = task; mData = data; } } }