Android AsyncTask原始碼解讀
屢思路
1. 初始 AsyncTask
AsyncTask
這個類的宣告如下:
public abstract class AsyncTask<Params, Progress, Result> { ..... }
是一個抽象類
Params
表示輸入引數的型別
Progress
表示後臺任務的執行進度
Result
表示返回結果的型別
2.使用
在AsyncTask
這個類的頂部有一些程式碼註釋,裡面講述瞭如何使用一個AsyncTask
,如下:
* <p>Here is an example of subclassing:</p> * <pre class="prettyprint"> * private 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"); *} * } * </pre> //user <p>Once created, a task is executed very simply:</p> * <pre class="prettyprint"> * new DownloadFilesTask().execute(url1, url2, url3); * </pre>
3. 內部重要方法
-
onPreExecute()
@MainThread protected void onPreExecute() { }
在主執行緒中執行,非同步任務之前會被呼叫,一般用於做一些準備工作;
-
doInBackground()
@WorkerThread protected abstract Result doInBackground(Params... params);
線上程池中執行,此方法一般用於執行非同步任務,通過publishProgress
方法來更新進度;
-
onProgressUpdate()
@MainThread protected void onProgressUpdate(Progress... values) { }
主執行緒中執行,當通過publishProgress
方法呼叫後,onProgressUpdate()
方法會被呼叫;
-
onPostExecute()
@MainThread protected void onPostExecute(Result result) { }
主執行緒中執行,將返回的結果展示。
4.原始碼分析
從它的execute
方法開始:
@MainThread public final AsyncTask<Params, Progress, Result> execute(Params... params) { //sDefaultExecutor 定義如下,執行緒池 return executeOnExecutor(sDefaultExecutor, params); } private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR; public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
@MainThread public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec, Params... params) { //首先判斷是不是 PENDING 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)"); } } //將狀態設定為 RUNNING 狀態 mStatus = Status.RUNNING; //1.呼叫了 onPreExecute() 方法 onPreExecute(); //將引數封裝到 mWorker.mParams 中去了 mWorker.mParams = params; //呼叫execute 將mFuture 傳進去了 exec.execute(mFuture); return this; }
為了弄明白整體流程,首頁要搞明白上面的mWorker
mFuture
是幹嘛的。
-
mWorker
private final WorkerRunnable<Params, Result> mWorker; //抽象類 並且實現了Callable 介面 private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> { Params[] mParams; } @SuppressWarnings({"RawUseOfParameterizedType"}) private static class AsyncTaskResult<Data> { final AsyncTask mTask; final Data[] mData; AsyncTaskResult(AsyncTask task, Data... data) { mTask = task; mData = data; } } }
//在AsyncTask 的構造方法中,分別對 mWorker, mFuture 進行了初始化 public AsyncTask(@Nullable Looper callbackLooper) { mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper() ? getMainHandler() : new Handler(callbackLooper); mWorker = new WorkerRunnable<Params, Result>() { //實現 了 call 方法 public Result call() throws Exception { //設定呼叫了為 true mTaskInvoked.set(true); // Result result = null; try { //設定執行緒的優先順序 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); //noinspection unchecked //將 2. doInBackground的結果儲存到 result 中 result = doInBackground(mParams); Binder.flushPendingCommands(); } catch (Throwable tr) { mCancelled.set(true); throw tr; } finally { //最後執行postResult postResult(result); } //返回結果 return result; } }; mFuture = new FutureTask<Result>(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 occurred while executing doInBackground()", e.getCause()); } catch (CancellationException e) { postResultIfNotInvoked(null); } } }; }
postResult(result)
方法
private Result postResult(Result result) { @SuppressWarnings("unchecked") Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT, new AsyncTaskResult<Result>(this, result)); message.sendToTarget(); return result; }
傳送一條MESSAGE_POST_RESULT
的訊息,並且將result
存入到了AsyncTaskResult
中的mData
中去了,
其中AsyncTaskResult
@SuppressWarnings({"RawUseOfParameterizedType"}) private static class AsyncTaskResult<Data> { final AsyncTask mTask; final Data[] mData; AsyncTaskResult(AsyncTask task, Data... data) { mTask = task; mData = data; } }
getHandler
獲取一個Handler
,我們看下handleMessage
的MESSAGE_POST_RESULT
對這條訊息的處理:
private static class InternalHandler extends Handler { public InternalHandler(Looper looper) { super(looper); } @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; } } }
其中result
是AsyncTaskResult
型別,前面我們見到過的,mTask
當時我們傳的是this
也就是當前的AsyncTask
,呼叫finish
方法,將mData
返回的結果傳入進去,還記得我們前面看過的嗎,將返回的結果存入AsyncTaskResult.mData
中去了。
下面看下finish
方法:
private void finish(Result result) { //判斷是否取消,如果取消了,就不執行onPostExecute 了 if (isCancelled()) { onCancelled(result); } else { //4. 就執行onPostExecute 方法了 onPostExecute(result); } // 將狀態標誌為 finish mStatus = Status.FINISHED; }
ok ,上述都是mWorker
工作的,接下來是我們一開始說的mFuture
-
mFuture
private final FutureTask<Result> mFuture; //初始化也是在AsyncTask 構造方法中執行的,在mWorker 之下,並且將mWorder 傳入 mFuture = new FutureTask<Result>(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 occurred while executing doInBackground()", e.getCause()); } catch (CancellationException e) { postResultIfNotInvoked(null); } } };
postResultIfNotInvoked(get());
如下:
private void postResultIfNotInvoked(Result result) { final boolean wasTaskInvoked = mTaskInvoked.get(); //wasTaskInvoked 為true ,之前在 mWorker 中設定了為true //mWorker = new WorkerRunnable<Params, Result>() { //public Result call() throws Exception { //mTaskInvoked.set(true); if (!wasTaskInvoked) { postResult(result); } }
FutureTask
:
我們知道mWorker implement Callable 介面,傳入賦值給了callable 變數 public FutureTask(Callable<V> callable) { if (callable == null) throw new NullPointerException(); this.callable = callable; this.state = NEW;// ensure visibility of callable } public void run() { if (state != NEW || !U.compareAndSwapObject(this, RUNNER, null, Thread.currentThread())) return; try { //callable 變數又賦值給了 c Callable<V> c = callable; if (c != null && state == NEW) { V result; boolean ran; try { //這裡呼叫c.call 實際上就是呼叫 mWorker.call 方法 //,由我們上面的分析知道,在mWorker.call 方法中最終會返回 result 結果 result = c.call(); ran = true; } catch (Throwable ex) { result = null; ran = false; setException(ex); } if (ran) set(result); } } finally { // runner must be non-null until state is settled to // prevent concurrent calls to run() runner = null; // state must be re-read after nulling runner to prevent // leaked interrupts int s = state; if (s >= INTERRUPTING) handlePossibleCancellationInterrupt(s); } }
ok ,這是mFuture
,還剩下最後一個:
exec.execute(mFuture);
exec
就是sDefaultExecutor
,其實 就是SerialExecutor
,如下:
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR; public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
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(); } } }); //第一次肯定為null ,執行 scheduleNext if (mActive == null) { scheduleNext(); } } protected synchronized void scheduleNext() { //給 mActivie 賦值,mTasks.poll 會從第一個開始取 if ((mActive = mTasks.poll()) != null) { THREAD_POOL_EXECUTOR.execute(mActive); } } }
上面我們將mFuture
傳入,實際就是r
.
mTask
是ArrayDeque<Runnable>
姑且認為它是這個排隊序列的吧。看下offer
方法:
/** 插入一個 element 在隊尾 * Inserts the specified element at the end of this deque. * * <p>This method is equivalent to {@link #offerLast}. * * @param e the element to add * @return {@code true} (as specified by {@link Queue#offer}) * @throws NullPointerException if the specified element is null */ public boolean offer(E e) { return offerLast(e); }
看註釋,也就是說是每次執行一個任務,都是在當前deque
的隊尾開始排隊的。並且執行是序列的,因為當第二個執行緒過來的時候,判斷mActive
不為null
將不會執行scheduleNext
.(我這個是8.0)原始碼,其實在android 3.0
之後AsyncTask
都是採用序列執行任務的。
各個版本的不同如下:
android 1.6
之前 ------序列
android 1.6-3.0
之間 ----- 並行
android 3.0
之後 ----- 序列
儘管如此,我們仍然可以通過 呼叫executeOnExecutor
來並行執行任務。
ok , 回到那個execute
方法中,我們說呼叫了r.run
實際山就是 呼叫mFuture.run
方法:
上面我們展示過在mFuture.run
方法中如下:
try { //這裡呼叫c.call 實際上就是呼叫 mWorker.call 方法 //,由我們上面的分析知道,在mWorker.call 方法中最終會返回 result 結果 result = c.call(); ran = true; } catch (Throwable ex) { result = null; ran = false; setException(ex); }
最終呼叫mWorker.call
方法,而在mWorker.call
方法中,我們完成一系列的任務,呼叫了doInBackground
onPostExecute
完成了整個的呼叫過程。
有的人可能已經注意到了 還差一個onProgressUpdate
方法還沒被呼叫,我們知道只有呼叫那個publishProgress
方法的時候才能呼叫onProgressUpdate
,那下面我們卡夏publishProgress
方法:
@WorkerThread protected final void publishProgress(Progress... values) { //如果沒取消 if (!isCancelled()) { //會發送一個 MESSAGE_POST_PROGRESS 的訊息getHandler().obtainMessage(MESSAGE_POST_PROGRESS, new AsyncTaskResult<Progress>(this, values)).sendToTarget(); } }
private static class InternalHandler extends Handler { public InternalHandler(Looper looper) { super(looper); } @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://是他是他 就是他 //3. 呼叫了 onProgressUpdate 方法了 result.mTask.onProgressUpdate(result.mData); break; } } }
會呼叫AsyncTask
的onProgressUpdate
方法了。結束。