相信各位对 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执行。这个过程实际就是模板模式。