本文簡單介紹Android中的AsyncTask,并從源碼角度分析它的流程和特點(diǎn)。
AsyncTask有助于使用UI線程。
這個(gè)類能讓你不主動使用多線程或Handler,在UI線程進(jìn)行后臺操作并發(fā)布結(jié)果。
是一個(gè)在不用多線程和Handler的情況下的幫助類。AsyncTask適用于短時(shí)間的操作(最多幾秒)。
如需長時(shí)間的線程操作,建議使用多線程包java.util.concurrent
中的API,比如Executor
,ThreadPoolExecutor
和 FutureTask
AsyncTask任務(wù)的構(gòu)成:
3種泛型:
Params
,Progress
和Result
4個(gè)步驟:
onPreExecute
,doInBackground
,onProgressUpdate
和onPostExecute
用法簡介
虛構(gòu)一個(gè)計(jì)算任務(wù)
/** * 虛擬的計(jì)算任務(wù) */ private class CalculationTask extends AsyncTask<Float, Integer, Float> { protected Float doInBackground(Float... inputs) { Log.d(TAG, "doInBackground thread ID = " + Thread.currentThread().getId()); long step = 0; float result = 0; for (float f : inputs) { // 假設(shè)這里有一些耗時(shí)的操作 result += f; } while (step < 5) { result += step; step++; publishProgress((int) step); } return result; } protected void onProgressUpdate(Integer... progress) { Log.d(TAG, "onProgressUpdate thread ID = " + Thread.currentThread().getId()); Log.d(TAG, "onProgressUpdate: " + progress[0]); } protected void onPostExecute(Float result) { Log.d(TAG, "onPostExecute thread ID = " + Thread.currentThread().getId()); Log.d(TAG, "任務(wù)執(zhí)行完畢"); } } // 執(zhí)行任務(wù) new CalculationTask().execute(1.2f, 2.3f, 6.3f);/*logcatMain thread ID = 1doInBackground thread ID = 8089onProgressUpdate thread ID = 1onProgressUpdate: 1...onProgressUpdate thread ID = 1onProgressUpdate: 5onPostExecute thread ID = 1任務(wù)執(zhí)行完畢*/
AsyncTask 使用的的泛型
AsyncTask使用的3種泛型
Params 送去執(zhí)行的類型
Progress 后臺計(jì)算的進(jìn)度類型
Result 后臺計(jì)算的結(jié)果
不用的泛型可以用Void
表示。例如
private class MyTask extends AsyncTask<Void, Void, Void> { ... }
異步任務(wù)的4個(gè)步驟
異步任務(wù)執(zhí)行時(shí)經(jīng)過4個(gè)步驟
onPreExecute()
UI線程在任務(wù)開始前調(diào)用這個(gè)方法。此方法常用來設(shè)置任務(wù),比如在屏幕上顯示一個(gè)進(jìn)度條。doInBackground(Params...)
onPreExecute()
執(zhí)行完畢后立即在后臺線程中執(zhí)行。這一步用來執(zhí)行耗時(shí)的后臺計(jì)算。
這個(gè)方法接受異步任務(wù)的參數(shù),返回最后的任務(wù)結(jié)果。這一步可以調(diào)用publishProgress(Progress...)
通知出去一個(gè)或多個(gè)進(jìn)度。這些進(jìn)度值會被onProgressUpdate(Progress...)
在UI線程收到。onProgressUpdate(Progress...)
調(diào)用publishProgress(Progress...)
后會在UI線程中執(zhí)行。用來顯示執(zhí)行中任務(wù)的UI。onPostExecute(Result)
后臺任務(wù)執(zhí)行完畢時(shí)被調(diào)用。最終結(jié)果會被傳入這個(gè)方法。
取消任務(wù)
調(diào)用cancel(boolean)
可隨時(shí)取消任務(wù)。取消任務(wù)后isCancelled()
會返回true。
調(diào)用這個(gè)方法后,后臺任務(wù)doInBackground(Object[])
執(zhí)行完畢后會調(diào)用onCancelled(Object)
而不再是onPostExecute(Object)
。
為保證任務(wù)能被及時(shí)地取消,在doInBackground(Object[])
中應(yīng)該經(jīng)常檢查isCancelled()
返回值
線程規(guī)則 Threading rules
一些線程規(guī)則
異步任務(wù)必須從UI線程啟動
必須在UI線程實(shí)例化AsyncTask類
必須在UI線程調(diào)用
execute(Params...)
不要手動調(diào)用
onPreExecute(), onPostExecute(Result), doInBackground(Params...), onProgressUpdate(Progress...)
同一個(gè)異步任務(wù)實(shí)例只能被執(zhí)行一次。重復(fù)執(zhí)行同一個(gè)異步任務(wù)實(shí)例會拋出異常(
IllegalStateException
)。
源碼簡析
需要解決的問題:
AsyncTask是如何調(diào)用后臺線程完成任務(wù)的?線程是如何調(diào)度的?
AsyncTask使用Executor
,利用WorkerRunnable
和FutureTask
來執(zhí)行后臺任務(wù)
private final WorkerRunnable<Params, Result> mWorker; // 實(shí)現(xiàn)了 Callable private final FutureTask<Result> mFuture; private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> { Params[] mParams; }
使用Handler
來進(jìn)行線程調(diào)度。內(nèi)部定義了一個(gè)類InternalHandler
。
從execute(Params... params)
方法切入
先看方法execute(Params... params)
,使用默認(rèn)執(zhí)行器,并傳入?yún)?shù)
調(diào)用xecuteOnExecutor(Executor exec, Params... params)
@MainThread // 指定在主線程執(zhí)行 public final AsyncTask<Params, Progress, Result> execute(Params... params) { return executeOnExecutor(sDefaultExecutor, params); }
先判斷當(dāng)前狀態(tài),如果狀態(tài)不是Status.PENDING
,則拋出異常。
否則進(jìn)入Status.RUNNING
狀態(tài),執(zhí)行onPreExecute()
,再由執(zhí)行器啟動任務(wù)。
@MainThread 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: // 同一個(gè)任務(wù)實(shí)例只能夠執(zhí)行一次 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); // 開始進(jìn)入后臺線程執(zhí)行任務(wù) return this; }
mWorker
帶著傳進(jìn)來的參數(shù),mFuture
實(shí)例化時(shí)已經(jīng)將mWorker
注入。參看構(gòu)造函數(shù)
public AsyncTask() { mWorker = new WorkerRunnable<Params, Result>() { public Result call() throws Exception { mTaskInvoked.set(true); Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); // 在后臺線程進(jìn)行自定義的操作 這里面可以調(diào)用publishProgress方法 Result result = doInBackground(mParams); Binder.flushPendingCommands(); return postResult(result); // 發(fā)送最終結(jié)果 } }; mFuture = new FutureTask<Result>(mWorker) { // 依賴 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); } } }; }
publishProgress
方法通過主線程的Handler向外通知進(jìn)度
@WorkerThread protected final void publishProgress(Progress... values) { if (!isCancelled()) { getHandler().obtainMessage(MESSAGE_POST_PROGRESS, new AsyncTaskResult<Progress>(this, values)).sendToTarget(); } }
后臺任務(wù)執(zhí)行完畢,postResult
發(fā)送最終結(jié)果
private Result postResult(Result result) { @SuppressWarnings("unchecked") Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT, new AsyncTaskResult<Result>(this, result)); message.sendToTarget(); // 會走到finish方法 return result; } private void finish(Result result) { if (isCancelled()) { onCancelled(result); // 如果任務(wù)已經(jīng)被取消了 } else { onPostExecute(result); // 通知任務(wù)執(zhí)行完畢 } mStatus = Status.FINISHED; }
關(guān)于默認(rèn)執(zhí)行器 sDefaultExecutor
和線程池
源碼中構(gòu)建了一個(gè)線程池和一個(gè)自定義的執(zhí)行器SerialExecutor
??克鼈儊韴?zhí)行后臺任務(wù)。
參考源代碼
public abstract class AsyncTask<Params, Progress, Result> { private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors(); // 核心線程至少2個(gè),最多4個(gè) 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; public static final Executor SERIAL_EXECUTOR = new SerialExecutor(); private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR; 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); public static final Executor THREAD_POOL_EXECUTOR; // 實(shí)際執(zhí)行者 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; } // 默認(rèn)執(zhí)行器的類 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); } } } }
backup at http://rustfisher.github.io/2017/06/22/Android_note/Android-AsyncTask/
http://www.cnblogs.com/rustfisher/p/7220998.html