AsyncTask做爲平常中一個常常被使用到的類,知道他的工做原理也是一件很是重要的事情。java
AsyncTask使用方法已經寫在下方的代碼中。android
/** * AsyncTask存在三個泛型類型 * 1。Params:輸入數據 * 2。Progress:相似於用於進度更新的返回值 * 3。Result:輸出的數據 */
public class MyTask extends AsyncTask<String, Integer, String> {
/** * 後臺操做 * @param strings * @return */
@Override
protected String doInBackground(String... strings) {
return null;
}
/** * 執行前的預處理 */
@Override
protected void onPreExecute() {
super.onPreExecute();
}
/** * 執行完成 * @param s */
@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
}
/** * 刷新獲得的新更新 * @param values */
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
}
/** * 任務取消 * @param s */
@Override
protected void onCancelled(String s) {
super.onCancelled(s);
}
/** * 任務取消 */
@Override
protected void onCancelled() {
super.onCancelled();
}
}
複製代碼
而Async的執行流程以下圖所示 git
通常咱們在代碼中只用執行excute()
的函數,在各個函數流程中給出相對應的操做。github
對應的項目寫在個人Github倉庫ide
MyTask task = new MyTask();
task.execute("。。");
複製代碼
在使用期間咱們是須要實例化這個對象的,那麼必經的入口就是他的構造函數了。函數
public AsyncTask(@Nullable Looper callbackLooper) {
mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper()
? getMainHandler()
: new Handler(callbackLooper);
mWorker = new WorkerRunnable<Params, Result>() {
public Result call() throws Exception {
mTaskInvoked.set(true);
Result result = null;
// 。。。
// 這裏出現了我必需要重寫的函數!!!
result = doInBackground(mParams);
// 。。。
// 把咱們獲得的數據傳輸了出去,發送到哪裏呢?
postResult(result);
return result;
}
};
mFuture = new FutureTask<Result>(mWorker) {
@Override
protected void done() {
// 。。。
// 一個必定會執行的函數
postResultIfNotInvoked(get());
// 。。。
}
};
}
private void postResultIfNotInvoked(Result result) {
// 任務標記
final boolean wasTaskInvoked = mTaskInvoked.get();
// 任務爲執行,則傳遞結果
if (!wasTaskInvoked) {
postResult(result);
}
}
複製代碼
在這裏我看到的都是一些數據的初始化,其實就是對任務完成的出口發送消息的定義、數據如何進行傳遞的定義等等。oop
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);
}
複製代碼
進入執行的第一句話,咱們就可以看到這樣一個函數,從字面意思我就可以知道了,是將數據放入了一個線程池。 爲了驗證咱們以前所說的執行流程咱們先進入executeOnExecutor ()
的函數。post
public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec, Params... params) {
// 。。。。
// 驗證了最開始的使用流程,excute執行後,調用的是onPreExecute
onPreExecute();
// 開始對任務進行了處理
mWorker.mParams = params;
exec.execute(mFuture);
return this;
}
複製代碼
回到咱們的執行流程中,咱們尚未了解咱們用的線程池他是怎樣的? 經過不斷的函數調用,咱們可以找到這樣的一個線程池內部類。學習
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(); // 1
}
}
});
if (mActive == null) {
scheduleNext(); // 1
}
}
protected synchronized void scheduleNext() {
// 從任務隊列中取出一個任務
if ((mActive = mTasks.poll()) != null) {
// 出現了另一個線程池來進行執行????
THREAD_POOL_EXECUTOR.execute(mActive);
}
}
}
複製代碼
其餘咱們先並不予以關注,你是否看到了scheduleNext()
這個必定會被調用的函數呢?並且裏面又出現了一個線程池。原來這個 THREAD_POOL_EXECUTOR
變量纔是真正的執行動做的線程池,那怎麼去看待上面的那個線程池呢?其實mTasks
這個變量已經告訴咱們答案了,他是一個進程存儲的進程任務隊列,而且execute()
是一個同步函數,因此 SerialExecutor
確切的說是一個進行按序任務調度的線程池。這樣也就證明了在不少博客中會說AsyncTask
是一個由兩個線程池和一個Handler組成的。this
前面講過了execute()
後面調用的函數是onPreExecute()
。而接下來的步驟就是doInBackground()
,回到先前的execute()
的代碼中,咱們知道會出現下面的代碼
exec.execute(mFuture);
// 上方操做調用的函數
public static void execute(Runnable runnable) {
sDefaultExecutor.execute(runnable);
}
複製代碼
咱們已經講過了sDefaultExecutor
他是一個任務調度的線程池,他會將任務發送給THREAD_POOL_EXECUTOR
進行完成,而他完成的mFuture
其實也是一個全局變量,我在構造函數中已經提到過了。
mWorker = new WorkerRunnable<Params, Result>() {
public Result call() throws Exception {
mTaskInvoked.set(true);
Result result = null;
try {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
// 由線程池執行完成時,用於回調的藉口
result = doInBackground(mParams);
Binder.flushPendingCommands();
} catch (Throwable tr) {
mCancelled.set(true);
throw tr;
} finally {
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);
}
}
};
複製代碼
這裏給讀者們看個全貌,做爲最後的回調接口中,咱們是否已經關注到了一個函數doInBackground()
這個函數呢? 目前爲止咱們已經完成了前三步,就差最後的一步onPostExecute()
的執行出現了,其實在上文就已經提到過了postResult(result)
這段代碼,就是進行一個結果的提交也就對應着咱們所說的onPostExecute()
。 咱們經過深刻了解能夠知道,就是經過Handler
將一個數據傳出去,這個時候既然結束了,那就對應的是一個finish()
函數。
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:
// 任務結束,返回數據。
result.mTask.finish(result.mData[0]);
break;
case MESSAGE_POST_PROGRESS:
// 獲得了publish的操做,來到這裏操做數據。
result.mTask.onProgressUpdate(result.mData);
break;
}
}
}
// 被調用的finish函數
private void finish(Result result) {
if (isCancelled()) {
onCancelled(result);
} else {
onPostExecute(result);
}
mStatus = Status.FINISHED;
}
複製代碼
到這裏,咱們完完整整的驗證了執行的流程。
以上就是個人學習成果,若是有什麼我沒有思考到的地方或是文章內存在錯誤,歡迎與我分享。
相關文章推薦: