標籤:asynctask 源碼
簡例
private class MyAsyncTask extends AsyncTask<String,Void,String>{ @Override protected String doInBackground(String... params) { String str = params[0]; return "disposed " + str; } @Override protected void onPostExecute(String s) { Log.e("TAG", s); super.onPostExecute(s); }}
new MyAsyncTask().execute("leelit");
內部邏輯
1、執行個體化AsyncTask,new MyAsyncTask();
public AsyncTask() { mWorker = new WorkerRunnable<Params, Result>() { public Result call() throws Exception { mTaskInvoked.set(true); Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); //noinspection unchecked return postResult(doInBackground(mParams)); } }; 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 occured while executing doInBackground()", e.getCause()); } catch (CancellationException e) { postResultIfNotInvoked(null); } } }; }
建構函式裡面執行個體化兩個對象,mWorker對象實現了Callable< result>,mFuture在這裡可以看作是對mWorker的一次封裝,他是一個FutureTask對象。
2、myAsyncTask.execute(params)
public final AsyncTask<Params, Progress, Result> execute(Params... params) { return executeOnExecutor(sDefaultExecutor, params); }
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: 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); return this; }
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
execute方法直接調用executeOnExecutor方法,在這個方法內部:
- 首先進行狀態的判斷和設定,這裡也說明一個AsyncTask對象只能execute一次,否則拋出異常;
- 然後執行一個onPreExecute()方法,這也是我們可以重寫的執行流程的第一個執行方法;
- 設定mWorker參數;
- 線程池執行任務。
注意,這裡的exec傳遞進來的是sDefaultExecutor,而sDefaultExecutor = SERIAL_EXECUTOR,從名字就可以看出他是串列執行任務的,接著看下去。
public static final Executor SERIAL_EXECUTOR = new 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(); } } }); if (mActive == null) { scheduleNext(); } } protected synchronized void scheduleNext() { if ((mActive = mTasks.poll()) != null) { THREAD_POOL_EXECUTOR.execute(mActive); } } }
上面這段代碼還是比較好明白的,就是串列執行任務的實現。裡面的線程池THREAD_POOL_EXECUTOR,各個版本也會有所不同,不過大多數任務隊列都設在了128。
private static final int CORE_POOL_SIZE = CPU_COUNT + 1; private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1; private static final int KEEP_ALIVE = 1; private static final BlockingQueue<Runnable> sPoolWorkQueue = new LinkedBlockingQueue<Runnable>(128); public static final Executor THREAD_POOL_EXECUTOR = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);
執行全過程
1、執行個體化MyAsyncTask對象,執行個體化mWorker對象和mFuture對象。
2、調用execute方法,判斷設定狀態,執行可選擇重寫的onPreExecute();方法,設定參數,內部線程池執行任務,exec.execute(mFuture)。
3、執行mWorker裡面的任務,調用doInBackground(mParams)方法,這也是必須重寫的,
4、執行postResult方法,將訊息發回主線程,postResult(doInBackground(mParams));
private Result postResult(Result result) { @SuppressWarnings("unchecked") Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT, new AsyncTaskResult<Result>(this, result)); message.sendToTarget(); return result; }
5、Handler處理訊息,這裡輾轉到最後就會調用重寫的需要在主線程處理的 onPostExecute(result);方法
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; } }
另外一個常用的方法是publishProgress,它也是通過Handler發送一個訊息給主線程去處理
getHandler().obtainMessage(MESSAGE_POST_PROGRESS, new AsyncTaskResult<Progress>(this, values)).sendToTarget();
小結
1、每個AsyncTask對象只能執行一次任務,因為其內部會有狀態判斷和設定;
2、內部共用一個線程池,任務隊列為128,串列順序執行任務,不過最後效果還是會看具體的線程池。
3、執行個體化AsyncTask對象,建構函式就是執行個體化一個 FutureTask對象,一旦運行就執行給定的 Callable。 這裡的Callable對象就是mWorker,其內部是執行doInBackground(mParams)方法,這也是必須重寫的,最後執行postResult方法,通過Handler將訊息發回主線程,postResult(doInBackground(mParams))。
執行個體化AsyncTask對象,就是執行個體化任務對象,這個任務內部調用重寫的方法;
調用執行方法就是線程池去執行任務,最後通過Handler來完成非同步通訊。
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。
Android:AsyncTask源碼解析