AsyncTask相信你们都不陌生,它是为了简化异步请求、更新UI操做而诞生的。使用它不只能够完成咱们的网络耗时操做,并且还能够在完成耗时操做后直接的更新咱们所须要的UI组件。这使得它在android开发中成为煊赫一时的网络请求工具类。android
而今天咱们就以源码分析的形式来完全的学习下它的实现过程。数组
首先,咱们先看看AsyncTask的定义形式:ruby
public abstract class AsyncTask<Params, Progress, Result> { }
首先AsyncTask它是一个抽象类,包括三种泛型类型,具体含义以下:微信
可是以上三个参数并非必定必须,在不须要时能够设置为Void,没有返回类型。网络
而后咱们看看它的执行过程,包括如下几个方法:异步
execute(Params... params),咱们在执行异步操做时会调用该方法,表示开始执行任务。ide
protected void onPreExecute() {},在调用execute方法后,该方法就会获得执行,它执行在UI线程中,用来初始化一些UI空间等工具
protected abstract Result doInBackground(Params... params);在onPreExecute执行完后将会执行该方法,它执行在后台,并接受一个Params类型的数组参数,用于请求网络,而且它返回一个Result 类型的结果。该方法中能够在执行网络请求的同时更新请求进度,调用publishProgress(Progress... values) 。oop
protected void onProgressUpdate(Progress... values) ,假如在doInBackground方法中调用了publishProgress方法,那么该方法就会获得执行,它是执行在UI线程的,根据values的值不停的更改进度,以达到想要的效果。源码分析
protected void onPostExecute(Result result),该方法是在doInBackground方法执行完毕后获得执行,可根据doInBackground返回的结果进行后续的UI操做,因而可知它是工做在UI线程中的。
通过上面一系列的方法运转,一个完整的AysncTask请求就正式的完成了任务。不只完成了耗时操做还更新的UI组件,这就是它的魅力所在。可是这时候你该有疑问了,上面的方法都是你说执行哪一个就执行哪一个,哪究竟是怎么执行的呢?
那么接下来就正式的揭开它的庐山正面目。
在正式介绍它的源码以前,你必须知道new 一个类它所执行的过程:
在new的过程当中,它会首先一层一层的加载它所继承的父类的成员变量及构造方法
而后在加载本身的成员变量和构造方法。
顺序是不可变得。
那么看看在咱们执行 new AsyncTask()中,它到底加载了哪些成员呢?
private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors(); 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 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 = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory); public static final Executor SERIAL_EXECUTOR = new SerialExecutor(); private static final int MESSAGE_POST_RESULT = 0x1; private static final int MESSAGE_POST_PROGRESS = 0x2; private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR; private static InternalHandler sHandler; private final WorkerRunnable<Params, Result> mWorker; private final FutureTask<Result> mFuture; private volatile Status mStatus = Status.PENDING; private final AtomicBoolean mCancelled = new AtomicBoolean(); private final AtomicBoolean mTaskInvoked = new AtomicBoolean(); private static class SerialExecutor implements Executor{...} public enum Status { PENDING, RUNNING, FINISHED, }
看到这么一大堆是否是很麻头皮,其实仔细拆分下来,你主要看几个变量便可。
THREAD_POOL_EXECUTOR :这个成员变量从它THREAD_POOL_EXECUTOR = new ThreadPoolExecutor中能够看出,它是一个线程池,而ThreadPoolExecutor线程池中须要几个参数,如corePoolSize(核心线程数)、maximumPoolSize(最大线程数)、workQueue(任务队列)、threadFactory(线程工程)等等,因此像CORE_POOL_SIZE,sPoolWorkQueue ,sThreadFactory 等成员变量,只是为了配置这个线程池而已。
sDefaultExecutor 这个成员变量是默认的线程调度任务,从上面可看出SERIAL_EXECUTOR则是一个序列化的任务调度,从sDefaultExecutor = SERIAL_EXECUTOR;中能够明确的知道sDefaultExecutor任务调度中是按前后顺序执行的。
sHandler顾名思义是一个handler,mWorker是一个工做线程,mFuture则是一个FutureTask,FutureTask是专门用于管理Runnable线程的,mStatus 则是一个枚举,里面有三种状态,分别是未执行,执行中,以及执行完成状态,默认状态是未执行状态。
因此咱们只要理解好上面几个变量能够不用惧怕它一堆的初始化成员。
而后咱们在看看AysncTask的构造方法中具体作了那些事:
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()); } 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); } } }; }
简单来讲,AsyncTask的成员变量中就只是初始化了两个变量,mWorker 和 mFuture 。这两个变量是很是重要的,后续的全部执行过程都是由这两个变量构成或引导的。
首先mWorker 是一个抽象内部类实例,是一个任务线程,它实现Callable
private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> { Params[] mParams; }
而后mFuture 则是一个针对任务线程的管理类。专门用于管理任务线程的,可使咱们的任务获得更好的控制,来看看它的构造方法吧:
public FutureTask(Callable<V> callable) { if (callable == null) throw new NullPointerException(); this.callable = callable; this.state = NEW; // ensure visibility of callable }
就是接受了咱们的mWorker 对象以及把自身的状态设置为NEW。
以上就是在new一个AsyncTask所进行的全部操做,无非就是初始化了一些数据和变量。
下面来看看AysncTask的正式执行。
咱们所知道开启一个AsyncTask任务所调用的方法是execute方法,该方法必须在主线程中调用。
public final AsyncTask<Params, Progress, Result> execute(Params... params) { return executeOnExecutor(sDefaultExecutor, params); }
在调用execute方法后,该方法什么也没作,只是把已初始化好的默认序列任务线程sDefaultExecutor和传递进来的数据params传递给了executeOnExecutor(),那么咱们在看看这个方法作了哪些事情:
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; }
executeOnExecutor()方法中首先判断了AsyncTask的执行状态,若是是正在执行或是已经结束执行了,它就会报出一个IllegalStateException的异常,告诉你线程或是在执行中或是已经执行完毕了。
只有在未执行的状态下,才能够进行AsyncTask请求任务,接下来它直接把AsyncTask的执行状态更改成Status.RUNNING,告诉其余任务该AsyncTask正在执行中,保持执行结果的一致性。而后就执行了onPreExecute();因为execute方法是必须在主线程中执行的,因此到目前为止仍是在主线程中运行,也就证实了onPreExecute()方法是在主线程中运行的。
protected void onPreExecute() { }
onPreExecute源码中并无作什么事情,这对于咱们来讲,只须要重写该方法就能够在主线程中进行一些UI组件的初始化等操做。
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); } }
源码咱们很清晰的知道在execute方法中最终的目的就是把mFuture任务线程赋值给一个Runnable 线程并放到了THREAD_POOL_EXECUTOR线程池中,由THREAD_POOL_EXECUTOR线程池来执行mFuture线程任务。
那么接着咱们看看在THREAD_POOL_EXECUTOR线程池中execute的方法中主要作了什么事情:
public void execute(Runnable command) { if (command == null) throw new NullPointerException(); int c = ctl.get(); if (workerCountOf(c) < corePoolSize) { if (addWorker(command, true)) return; c = ctl.get(); } if (isRunning(c) && workQueue.offer(command)) { int recheck = ctl.get(); if (! isRunning(recheck) && remove(command)) reject(command); else if (workerCountOf(recheck) == 0) addWorker(null, false); } else if (!addWorker(command, false)) reject(command); }
THREAD_POOL_EXECUTOR线程池中主要是判断了传递的线程是否为空,是否小于当前线程池中保存的核心线程数,若是小于则直接执行addWorker(command, true)方法,下面看看addWorker方法中的实现内容:
private boolean addWorker(Runnable firstTask, boolean core) { ...(前面代码省略) boolean workerStarted = false; boolean workerAdded = false; Worker w = null; try { w = new Worker(firstTask); final Thread t = w.thread; if (t != null) { final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { int rs = runStateOf(ctl.get()); if (rs < SHUTDOWN || (rs == SHUTDOWN && firstTask == null)) { if (t.isAlive()) throw new IllegalThreadStateException(); workers.add(w); int s = workers.size(); if (s > largestPoolSize) largestPoolSize = s; workerAdded = true; } } finally { mainLock.unlock(); } if (workerAdded) { t.start(); workerStarted = true; } } } finally { if (! workerStarted) addWorkerFailed(w); } return workerStarted; }
咱们只看主要的逻辑,首先是将咱们的mFuture任务线程存放到了一个Worker的对象中,而后又从Worker对象中获取到mFuture线程并赋值给了Thread ,接着把Worker对象放到workers的HashSet数据集合对象中,通过获取HashSet的大小并进行一些判断,把workerAdded 设置为true,最后开启t.start();线程,由此进入了子线程中。
那么接下来在开启的子线程中又作了什么事情呢?
咱们从上面的分析指导t.start()开启就是一个mFuture的异步任务线程,那么它在哪执行呢?
细心的朋友能够发现,原来是在SerialExecutor 中的execute方法中咱们的mFuture的run()早已在等待了线程的启动,那么,我如今去看看mFuture的run()方法中作了什么工做吧
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 = null; int s = state; if (s >= INTERRUPTING) handlePossibleCancellationInterrupt(s); } }
这段代码很简单,一眼就能够看得出来就是利用咱们在为mFuture初始化时传递的mWorker 对象实例并调用它的call()方法,咱们先无论call怎么实现的,先来看看这个方法中的后续是什么。
接着它获得一个执行结果,并把一个boolean类型的ran设置为true,最后根据ran调用set(result);方法,并把结果传递进去,下面看看set的源码:
protected void set(V v) { if (U.compareAndSwapInt(this, STATE, NEW, COMPLETING)) { outcome = v; U.putOrderedInt(this, STATE, NORMAL); // final state finishCompletion(); } }
它主要调用了finishCompletion();在来看看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 }
在执行完call中,把一些对象进行还原,还调用了 done(),该方法就是在AsyncTask构造方法中咱们有看到它的实现:
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); } } };
咱们也说过FutureTask主要是用来管理异步线程任务的,那么在done方法中就有很好的体现,在该方法中,它会判断执行的结果是否成功,成功后有没有被发送,若是有发送它就再也不发送消息,若是结果执行成功,但没有被发送它就会发送最终的执行结果:
private void postResultIfNotInvoked(Result result) { final boolean wasTaskInvoked = mTaskInvoked.get(); if (!wasTaskInvoked) { postResult(result); } }
postResult方法的内容咱们推后一点讲,那么如今咱们来看看mWorker 中call()是怎么实现的:
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); } };
在这里咱们终于见到了咱们所熟悉的一个方法doInBackground(),由此也能够知道其确实是在子线程运行的,而doInBackground()方法在AsyncTask类中是一个抽象方法:
protected abstract Result doInBackground(Params... params);
那么咱们在重写doInBackground()时就能够直接的在其中进行一些耗时的网络和IO操做了。
这里插上一句,假如在doInBackground()调用了publishProgress方法来更新进度的话,那来看看它是怎么作的:
protected final void publishProgress(Progress... values) { if (!isCancelled()) { getHandler().obtainMessage(MESSAGE_POST_PROGRESS, new AsyncTaskResult<Progress>(this, values)).sendToTarget(); } }
publishProgress方法中主要是经过Hangler发送一条更新进度的标志用来更新进度。这里的Hangler接受消息在下面和执行结果一块儿讲。
最后doInBackground()执行获取的Result 结果也将会传递到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; } private static Handler getHandler() { synchronized (AsyncTask.class) { if (sHandler == null) { sHandler = new InternalHandler(); } return sHandler; } } private static class AsyncTaskResult<Data> { final AsyncTask mTask; final Data[] mData; AsyncTaskResult(AsyncTask task, Data... data) { mTask = task; mData = data; } }
postResult中首先封装了doInBackground异步执行结果的AsyncTaskResult对象,而后获取到一个Handler ,经过消息处理机制发送一条信息来切换到主线程中进行UI界面的更换,消息处理机制不属于本次博文的内容因此再也不细说,那来看看这个Handler是怎么处理这个消息内容的。
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.what) { case MESSAGE_POST_RESULT: result.mTask.finish(result.mData[0]); break; case MESSAGE_POST_PROGRESS: result.mTask.onProgressUpdate(result.mData); break; } } }
Handler中主要是根据消息标志进行区分是更新进度仍是执行结果:
若是是更新进度则调用AsyncTask的onProgressUpdate方法来更新内容,因为经过Handler已转变为主线程中,因此咱们在重写该方法时能够直接更新UI组件。
若是是执行结果则AsyncTask的finish(result.mData[0]);并把结果数据传递过去,来看看finish()中是怎么实现的:
private void finish(Result result) { if (isCancelled()) { onCancelled(result); } else { onPostExecute(result); } mStatus = Status.FINISHED; }
finish()方法中也很是的简单,首先判断是否为取消线程,不然的话则执行onPostExecute(result)方法,由此咱们在重写了onPostExecute方法后能够直接的更新咱们的UI组件。
最后把AsyncTask的状态改成完成状态,至此整个AsyncTask生命周期就执行完毕了。
好了,至此AsyncTask整个执行过程就彻底讲完了,相信你们也学到了很多东西,建议你们有空本身对着源码在梳理一遍,毕竟本身总结出来的印象就更深入。
今天就到这里吧,祝你们生活愉快。
更多资讯请关注微信平台,有博客更新会及时通知。爱学习爱技术。