Android总结 之 AsyncTask(二)
首先從AsyncTask的execute方法開始介紹,這是AsyncTask的入口:
public final AsyncTask<Params, Progress, Result> execute(Params... params) {return executeOnExecutor(sDefaultExecutor, params);}執行的是他的重載函數executeOnExecutor,其中處理器Executor是sDefaultExecutor,我們先把它放在一邊,先看它的重載函數executeOnExecutor:
public final AsyncTask<Params, Progress, Result> 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();mWorker.mParams = params;exec.execute(mFuture);return this;}這里我們看到有每個任務有三個狀態PENDING,RUNNING和FINISHED,其中只有在任務是PENDING時,任務才會往下執行,并把任務的狀態設置成Running
public enum Status {// 表示task沒有運行PENDING,RUNNING,FINISHED,}onPreExecute();是抽象函數,需要用戶去重寫。mWorker和mFuture是什么東東呢?繼續往下看。
mWorker = new WorkerRunnable<Params, Result>() {public Result call() throws Exception {mTaskInvoked.set(true);Result result = null;try {Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);//noinspection uncheckedresult = doInBackground(mParams);Binder.flushPendingCommands();} catch (Throwable tr) {mCancelled.set(true);throw tr;} finally {postResult(result);}return result;}};mFuture = new FutureTask<Result>(mWorker) {@Overrideprotected void done() {try {postResultIfNotInvoked(get());} catch (InterruptedException e) {android.util.Log.w(LOG_TAG, e);} catch (ExecutionException e) {throw new RuntimeException("An error occurred while executing doInBackground()",e.getCause());} catch (CancellationException e) {postResultIfNotInvoked(null);}}};}mWorker是WorkerRunnable的子類,WorkerRunnable只是一個添加了mParams的Callable,實現了Callable的類必須實現他的call方法,call方法能獲得并返回結果。將一個callable子類作為FutureTask的參數,可以接收運算的結果,這里FutureTask通過get方獲得結果,采用通知的方式,不會阻塞線程。
private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> {Params[] mParams;}知道了這么多東西,可能有點亂了,這里講解到了這里:
//AsyncTask的executeOnExecutor方法mStatus = Status.RUNNING;onPreExecute();mWorker.mParams = params;//這里exec.execute(mFuture);return this;exec.execute(mFuture); 這里是最重要的部分,我們先回頭看一下executeOnExecutor(sDefaultExecutor, params);中的sDefaultExecutor
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;public static final Executor SERIAL_EXECUTOR = new SerialExecutor();從名字可以看出來,這是一個串行的執行器。
private static class SerialExecutor implements Executor {final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();Runnable mActive;public synchronized void execute(final Runnable r) {mTasks.offer(new Runnable() {public void run() {try {r.run();} finally {scheduleNext();}}});if (mActive == null) {scheduleNext();}}protected synchronized void scheduleNext() {if ((mActive = mTasks.poll()) != null) {THREAD_POOL_EXECUTOR.execute(mActive);}}}我們可以大致了解到,mTasks是一個數組雙向隊列,這是一個環狀的數組,有興趣的同學可以看看。
SerialExecutor用于Runnable的調度,它將Runnable進行簡單的包裝,并保存到隊里中。經過包裝后,不僅會執行原始提交Runnable的代碼,并且會執行結束后用THREAD_POOL_EXECUTOR調用隊列中的下一個Runnable。這時候就要去思考了,THREAD_POOL_EXECUTOR是什么東東呢?
private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4));private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;private static final int KEEP_ALIVE_SECONDS = 30;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());}};private static final BlockingQueue<Runnable> sPoolWorkQueue =new LinkedBlockingQueue<Runnable>(128);/*** An {@link Executor} that can be used to execute tasks in parallel.*/public static final Executor THREAD_POOL_EXECUTOR;static {ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS,sPoolWorkQueue, sThreadFactory);threadPoolExecutor.allowCoreThreadTimeOut(true);THREAD_POOL_EXECUTOR = threadPoolExecutor;}從這里看出,這是一個線程池,也就是說SerialExecutor保證任務在隊列中的順序,然后自己一邊執行任務,一邊交給線程池THREAD_POOL_EXECUTOR執行,這是線程池是并行執行任務的:
好了,執行任務excute方法搞定了,那對于返回的結果,AsyncTask是怎么處理的呢?我們知道,回調這個操作是由Callable接口中的call()方法執行,通過 postResult(result);返回結果。
mWorker = new WorkerRunnable<Params, Result>() {public Result call() throws Exception {mTaskInvoked.set(true);Result result = null;try {Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);//noinspection uncheckedresult = doInBackground(mParams);Binder.flushPendingCommands();} catch (Throwable tr) {mCancelled.set(true);throw tr;} finally {postResult(result);}return result;}};因為安卓的ui要在主線程中更新,postResult實際上就是新線程向主線程發送消息,讓主線程去更新ui。
private Result postResult(Result result) {@SuppressWarnings("unchecked")Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,new AsyncTaskResult<Result>(this, result));message.sendToTarget();return result;}讓我們先看看這個Handler到底是什么東西。
private static Handler getMainHandler() {synchronized (AsyncTask.class) {if (sHandler == null) {sHandler = new InternalHandler(Looper.getMainLooper());}return sHandler;}}可以看到這是一個AsyncTask的靜態內部類InternalHandler,看看它做了什么?
private static class InternalHandler extends Handler {public InternalHandler(Looper looper) {super(looper);}@SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})@Overridepublic void handleMessage(Message msg) {AsyncTaskResult<?> result = (AsyncTaskResult<?>) msg.obj;switch (msg.what) {case MESSAGE_POST_RESULT:// There is only one resultresult.mTask.finish(result.mData[0]);break;case MESSAGE_POST_PROGRESS:result.mTask.onProgressUpdate(result.mData);break;}}}可以看到,它定義了一個handleMessage方法,我們先賣個關子,知道它定義了一個handleMessaage方法。
繼續看回來PostResult方法:
private Result postResult(Result result) {@SuppressWarnings("unchecked")Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,new AsyncTaskResult<Result>(this, result));message.sendToTarget();return result;}我們知道了Handler是InternalHandler,而且知道它繼承了Handler并重寫了一個handleMessaage方法,obtainMessage()方法是用來干什么的呢?
// Handler中的obtainMessage方法,調用了message的obtain并將自己的指針扔進去public final Message obtainMessage(int what, Object obj){return Message.obtain(this, what, obj);} // Message 中的Obtain方法public static Message obtain(Handler h, int what, Object obj) {Message m = obtain();m.target = h;m.what = what;m.obj = obj;return m;}obtainMessage方法很簡單,只是用來構造一個Message對象而已,值得一提的是這個對象的target是handler
ok,我們拿到了一個Handler,并用Handler構造出了一個Message對象,接下來要怎么處理呢?看一下postResule的 message.sendToTarget()方法,最終調用了Handler的sendMessageAtTime方法
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {MessageQueue queue = mQueue;if (queue == null) {RuntimeException e = new RuntimeException(this + " sendMessageAtTime() called with no mQueue");Log.w("Looper", e.getMessage(), e);return false;}return enqueueMessage(queue, msg, uptimeMillis);}這里得到Handler里面的的mQueue隊列,并執行enqueueMessage方法,這里大家應該能猜到,它想把這個message作入隊列的操作把?驗證一下
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {msg.target = this;if (mAsynchronous) {msg.setAsynchronous(true);}return queue.enqueueMessage(msg, uptimeMillis);}完成入隊之后,mQueue這個隊列同樣是Looper類的成員,我們可以猜想Looper就是用來遍歷queue的,來看看是不是
loop(){for (;;) {Message msg = queue.next(); // might blockif (msg == null) {// No message indicates that the message queue is quitting.return;}msg.target.dispatchMessage(msg);}}果然是用來遍歷queue的,最后調用的是 msg.target.dispatchMessage(msg);方法,這時候我們聯想到上面message的Objtain方法,把當前hander作為Message的target,所以msg.target得到的就是處理這個message的handler。
public void dispatchMessage(Message msg) {if (msg.callback != null) {handleCallback(msg);} else {if (mCallback != null) {if (mCallback.handleMessage(msg)) {return;}}handleMessage(msg);}}dispactchMessage(mes)是InternalHandler中的方法,調用了它的唯一重寫的方法handleMessage。這就是我們當時看InternalHandler的那個伏筆,哈哈
那我們在回頭看看InternalHandler把!
private static class InternalHandler extends Handler {public InternalHandler(Looper looper) {super(looper);}@SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})@Overridepublic void handleMessage(Message msg) {AsyncTaskResult<?> result = (AsyncTaskResult<?>) msg.obj;switch (msg.what) {case MESSAGE_POST_RESULT:// There is only one resultresult.mTask.finish(result.mData[0]);break;case MESSAGE_POST_PROGRESS:result.mTask.onProgressUpdate(result.mData);break;}}}InternalHandler的handleMessage就是簡單的處理結果:最后調用finish方法,我們來看一下。
private void finish(Result result) {if (isCancelled()) {onCancelled(result);} else {onPostExecute(result);}mStatus = Status.FINISHED;}最后調用了onPostExecute,也是重寫AsyncSTask可以選擇重寫的方法, 主要執行異步得到結果之后,主線程對ui的處理。
總結
以上是生活随笔為你收集整理的Android总结 之 AsyncTask(二)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: kotlin学习之泛型(十四)
- 下一篇: Android总结 之 View系统学习