基于 Android-24
AsyncTask 是安卓 sdk 提供的一個(gè)異步框架气嫁,用來(lái)解決耗時(shí)任務(wù)線(xiàn)程和主線(xiàn)程之間通訊問(wèn)題攀痊。
但是因?yàn)?sdk 升級(jí)過(guò)程中的幾次重大改動(dòng)义图,導(dǎo)致 AsyncTask 有了很多『坑』
但是不可否認(rèn) AsyncTask 框架的設(shè)計(jì)栖忠,還有值得學(xué)習(xí)的咽瓷。
AsyncTask 框架
AsyncTask 核心代碼只有一個(gè)文件设凹,其中包含
3 個(gè)靜態(tài)內(nèi)部類(lèi)
1 個(gè)靜態(tài)內(nèi)部抽象類(lèi)
1 個(gè)枚舉類(lèi)
1 個(gè) AsyncTask 類(lèi)
使用方法
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();
三個(gè)泛型參數(shù)分別代表:傳入?yún)?shù)類(lèi)型、任務(wù)進(jìn)度單位茅姜、返回結(jié)果類(lèi)型
AsyncTask 線(xiàn)程池管理
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();
// 核心線(xiàn)程數(shù)最小為2 闪朱,最大為 4 。根據(jù) cpu 核數(shù)確定钻洒。
private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4));
// 最大線(xiàn)程數(shù)量為 cpu 核數(shù)的 2 倍 - 1
private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
// 非核心線(xiàn)程數(shù)存活時(shí)間為 30s
private static final int KEEP_ALIVE_SECONDS = 30;
AsyncTask 創(chuàng)建的線(xiàn)程奋姿,都會(huì)用 『AsyncTask #』開(kāi)頭標(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ù)隊(duì)列長(zhǎng)度為 128
private static final BlockingQueue<Runnable> sPoolWorkQueue =
new LinkedBlockingQueue<Runnable>(128);
關(guān)于線(xiàn)程池參數(shù)含義參考Java 線(xiàn)程池源碼閱讀筆記
AsyncTask 任務(wù)執(zhí)行過(guò)程
-
execute 方法
AsyncTask 有三個(gè) execute 方法。 1.直接通過(guò)內(nèi)置線(xiàn)程調(diào)度器素标,執(zhí)行一個(gè) runnable public static void execute(Runnable runnable) 2.使用內(nèi)置線(xiàn)程調(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) 其中『第二種』方法癣诱,會(huì)調(diào)用『第三種』方法,不過(guò)是將內(nèi)置的線(xiàn)程調(diào)度器傳遞過(guò)去
-
sDefaultExecutor 成員變量
sDefaultExecutor 是一個(gè)線(xiàn)性調(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 類(lèi)有以下幾個(gè)特點(diǎn)
1. execute 和 scheduleNext 方法都持有一個(gè)對(duì)像鎖袜香。
2. 如果隊(duì)列 mTasks 不為空撕予,mActive 則不為空。
3. mActive 為空困鸥,則表示隊(duì)列已空嗅蔬,執(zhí)行 scheduleNext 執(zhí)行隊(duì)列剛添加的任務(wù)。
4. mActive 不為空疾就,添加任務(wù)到隊(duì)列尾部澜术。等待任務(wù)出棧。
流程圖大致如下
-
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()); } …… } }; }
通過(guò)以上代碼,可以得出
1. AsyncTask 任務(wù)封裝到 FutureTask 中姑荷。 2. 在執(zhí)行任務(wù)之前先執(zhí)行 onPreExecute()盒延,此時(shí)依舊在主線(xiàn)程。 3. doInBackground() 在線(xiàn)程成中執(zhí)行鼠冕。 4. 任務(wù)執(zhí)行完畢會(huì)執(zhí)行 postResult 或者 postResultIfNotInvoked 發(fā)送消息給主線(xiàn)程
-
返回結(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; }
通過(guò) postResult 方法返回結(jié)果給主線(xiàn)程添寺。
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; } }
最終會(huì)調(diào)用 finish 方法
private void finish(Result result) {
if (isCancelled()) {
onCancelled(result);
} else {
onPostExecute(result);
}
mStatus = Status.FINISHED;
}
- 總結(jié) AsyncTask 框架的時(shí)序圖如下