相信各位對 AsyncTask 不會陌生,雖然它有以下弊端:html
1. 若是在activiy內部new 一個AsyncTask, 橫豎屏切換生成一個新的activity,等結果返回時,處理很差容易出現NPE。android
2. 容易出現內存泄漏,若是AsyncTask 進行比較耗時的IO操做(網絡操做, 打開一個文件等等),在activity onDestroy的時候沒有cancel的話,網絡
致使該Activity不能被GC回收(AsyncTask 在Activity內部執行耗時操做)。less
3. 若是調用 executeOnExecutor, 若是等待queue裏面的請求過多沒有獲得及時處理,容易形成RejectException, 具體緣由我在個人博客已經有所介紹(AsyncTask RejectedExecutionException 小結)。ide
閒話少說, 本文的重點不在於介紹AsyncTask的優缺點,而是一直有一個問題困擾我,爲何AsyncTask 裏面既能進行UI 操做,又能進行耗時的操做。函數
讓咱們從代碼角度來分析這個問題, 首先看他的構造函數:oop
public AsyncTask() { mWorker = new WorkerRunnable<Params, Result>() { public Result call() throws Exception { mTaskInvoked.set(true); Result result = null; try { Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); //noinspection unchecked 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); } } }; }
private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> { Params[] mParams; }
public class FutureTask<V> implements RunnableFuture<V>
public interface Callable<V> { /** * Computes a result, or throws an exception if unable to do so. * * @return computed result * @throws Exception if unable to compute a result */ V call() throws Exception; }
public interface RunnableFuture<V> extends Runnable, Future<V> { /** * Sets this Future to the result of its computation * unless it has been cancelled. */ void run(); }
從上面的代碼能夠看出, mWorker 實際上就是一個 Callable, 而 mFuture 就是一個Thread, 構造函數中將Callable 做爲參數傳給了 FutureTask,下面post
咱們看看FutureTask 中的相關實現:this
public void run() { if (state != NEW || !U.compareAndSwapObject(this, RUNNER, null, Thread.currentThread())) return; try { Callable<V> c = callable; if (c != null && state == NEW) { V result; boolean ran; try { result = c.call(); ran = true; } catch (Throwable ex) { result = null; ran = false; setException(ex); } if (ran) set(result); } } finally { // runner must be non-null until state is settled to // prevent concurrent calls to run() runner = null; // state must be re-read after nulling runner to prevent // leaked interrupts int s = state; if (s >= INTERRUPTING) handlePossibleCancellationInterrupt(s); } }
protected void set(V v) { if (U.compareAndSwapInt(this, STATE, NEW, COMPLETING)) { outcome = v; U.putOrderedInt(this, STATE, NORMAL); // final state finishCompletion(); } }
private void finishCompletion() { // assert state > COMPLETING; for (WaitNode q; (q = waiters) != null;) { if (U.compareAndSwapObject(this, WAITERS, q, null)) { for (;;) { Thread t = q.thread; if (t != null) { q.thread = null; LockSupport.unpark(t); } WaitNode next = q.next; if (next == null) break; q.next = null; // unlink to help gc q = next; } break; } } done(); callable = null; // to reduce footprint }
能夠看到 result = c.call(); 在run方法中被調用, 實際就是 result = doInBackground(mParams); 被調用,由於該方法是在子線程裏面執行,因此能夠執行耗時操做。 繼續讀代碼,call-> set(result) -> finishCompletion->done()-> postResultIfNotInvoked-> postResulturl
private Result postResult(Result result) { @SuppressWarnings("unchecked") Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT, new AsyncTaskResult<Result>(this, result)); message.sendToTarget(); return result; }
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()); } @SuppressWarnings({"unchecked", "RawUseOfParameterizedType"}) @Override public void handleMessage(Message msg) { AsyncTaskResult<?> result = (AsyncTaskResult<?>) msg.obj; switch (msg.wh因此at) { 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; } } }
相信上面的代碼你們都能看懂,值得說明的是,由於 InternalHandler的構造函數使用 mainlooper,因此 handleMessage 固然能夠進行UI 操做。
繼續看源碼:
private void finish(Result result) { if (isCancelled()) { onCancelled(result); } else { onPostExecute(result); } mStatus = Status.FINISHED; }
總結一下,虛函數 doInBackground 在Thread(FutureTask)run方法執行,因此能進行耗時操做,而InternalHanlder 經過得到mainlooper,在 handleMessage中調用 onPostExecute 從而保證了UI 操做能夠在onPostExecute執行。這個過程實際就是模板模式。