基于 Android-24
AsyncTask 是安卓 sdk 提供的一個異步框架,用來解決耗時任務(wù)線程和主線程之間通訊問題。
但是因為 sdk 升級過程中的幾次重大改動,導(dǎo)致 AsyncTask 有了很多『坑』
asyncTask_01.png
但是不可否認(rèn) AsyncTask 框架的設(shè)計,還有值得學(xué)習(xí)的。
AsyncTask 框架
AsyncTask 核心代碼只有一個文件,其中包含
3 個靜態(tài)內(nèi)部類
1 個靜態(tài)內(nèi)部抽象類
1 個枚舉類
1 個 AsyncTask 類
asyncTask_03.png
使用方法
new AsyncTask<Object,Object,Object>(){
@Override
protected Object doInBackground(Object[] params) {
return null;
}
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected void onPostExecute(Object o) {
super.onPostExecute(o);
}
}.execute();
三個泛型參數(shù)分別代表:傳入?yún)?shù)類型、任務(wù)進(jìn)度單位、返回結(jié)果類型
AsyncTask 線程池管理
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;
}
其中:
private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
// 核心線程數(shù)最小為2 ,最大為 4 。根據(jù) cpu 核數(shù)確定。
private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4));
// 最大線程數(shù)量為 cpu 核數(shù)的 2 倍 - 1
private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
// 非核心線程數(shù)存活時間為 30s
private static final int KEEP_ALIVE_SECONDS = 30;
AsyncTask 創(chuàng)建的線程,都會用 『AsyncTask #』開頭標(biāo)記
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());
}
};
AsyncTask 的任務(wù)隊列長度為 128
private static final BlockingQueue<Runnable> sPoolWorkQueue =
new LinkedBlockingQueue<Runnable>(128);
關(guān)于線程池參數(shù)含義參考Java 線程池源碼閱讀筆記
AsyncTask 任務(wù)執(zhí)行過程
-
execute 方法
AsyncTask 有三個 execute 方法。 1.直接通過內(nèi)置線程調(diào)度器,執(zhí)行一個 runnable public static void execute(Runnable runnable) 2.使用內(nèi)置線程調(diào)度器,傳入?yún)?shù)執(zhí)行 doInBackground 中的任務(wù)。 public final AsyncTask<Params, Progress, Result> execute(Params... params) 3.使用自定義任務(wù)調(diào)度器,傳入?yún)?shù)執(zhí)行 doInBackground 中的任務(wù)。 public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec, Params... params) 其中『第二種』方法,會調(diào)用『第三種』方法,不過是將內(nèi)置的線程調(diào)度器傳遞過去
-
sDefaultExecutor 成員變量
sDefaultExecutor 是一個線性調(diào)度器
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); } }
}
SerialExecutor 類有以下幾個特點
1. execute 和 scheduleNext 方法都持有一個對像鎖。
2. 如果隊列 mTasks 不為空,mActive 則不為空。
3. mActive 為空,則表示隊列已空,執(zhí)行 scheduleNext 執(zhí)行隊列剛添加的任務(wù)。
4. mActive 不為空,添加任務(wù)到隊列尾部。等待任務(wù)出棧。
流程圖大致如下
asyncTask_02.png
-
executeOnExecutor() 方法
public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec, Params... params) { if (mStatus != Status.PENDING) { …… } mStatus = Status.RUNNING; onPreExecute(); mWorker.mParams = params; exec.execute(mFuture); return this; }
executeOnExecutor 方法中執(zhí)行了 onPreExecute() ,然后執(zhí)行 exec.execute(mFuture)。
其中 mFuture 代碼如下public AsyncTask() { mWorker = new WorkerRunnable<Params, Result>() { public Result call() throws Exception { mTaskInvoked.set(true); Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); //noinspection unchecked Result result = doInBackground(mParams); Binder.flushPendingCommands(); return postResult(result); } }; mFuture = new FutureTask<Result>(mWorker) { @Override protected void done() { try { postResultIfNotInvoked(get()); } …… } }; }
通過以上代碼,可以得出
1. AsyncTask 任務(wù)封裝到 FutureTask 中。 2. 在執(zhí)行任務(wù)之前先執(zhí)行 onPreExecute(),此時依舊在主線程。 3. doInBackground() 在線程成中執(zhí)行。 4. 任務(wù)執(zhí)行完畢會執(zhí)行 postResult 或者 postResultIfNotInvoked 發(fā)送消息給主線程
-
返回結(jié)果
private void postResultIfNotInvoked(Result result) { final boolean wasTaskInvoked = mTaskInvoked.get(); if (!wasTaskInvoked) { 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; }
通過 postResult 方法返回結(jié)果給主線程。
private static Handler getHandler() { synchronized (AsyncTask.class) { if (sHandler == null) { sHandler = new InternalHandler(); } return sHandler; } } private static class InternalHandler extends Handler { public InternalHandler() { super(Looper.getMainLooper()); } @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; } }
最終會調(diào)用 finish 方法
private void finish(Result result) {
if (isCancelled()) {
onCancelled(result);
} else {
onPostExecute(result);
}
mStatus = Status.FINISHED;
}
- 總結(jié) AsyncTask 框架的時序圖如下
asyncTask_04.png