一个简单的栗子
new AsyncTask<Void, Integer, Boolean>() {
@Override
protected Boolean doInBackground(Void... voids) {
//在子线程中运行的代码
return null;
}
@Override
protected void onPreExecute() {
//后台任务开始执行之间调用,用于进行一些界面上的初始化操作
super.onPreExecute();
}
@Override
protected void onPostExecute(Boolean aBoolean) {
//后台任务执行完后调用,可以提示执行的结果
super.onPostExecute(aBoolean);
}
@Override
protected void onProgressUpdate(Integer... values) {
//可以在这里更新UI进度的操作
super.onProgressUpdate(values);
}
@Override
protected void onCancelled(Boolean aBoolean) {
//取消操作
super.onCancelled(aBoolean);
}
@Override
protected void onCancelled() {
super.onCancelled();
}
}.execute();
源码剖析
- 先从类的静态块开始看起
private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors(); 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; 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; 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; } public static final Executor SERIAL_EXECUTOR = new SerialExecutor(); private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
可以看到,AsyncTask一次可以执行的最大线程数为Math.max(2, Math.min(CPU_COUNT - 1, 4))个,队列中一次最多只能存储128个线程,并且构造了一个线程池来管理可能执行的任务, 这里有个细节,可以看静态块中的代码,THREAD_POOL_EXECUTOR是在新建实例并执行完allowCoreThreadTimeOut函数后才指向这个实例的地址的,这样的好处是保证了状态的初始化。
- 然后是构造函数,所有的构造函数最终都是调用这个进行构造实例:
public AsyncTask(@Nullable Looper callbackLooper) { mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper() ? getMainHandler() : new Handler(callbackLooper); 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); } } }; }
整个构造流程主要分为三步:
-
获取handler 如果传入的looper为null或者为主线程,则把引用指向主线程的hanlder,否则则通过传入的looper构造一个hanlder
-
初始化mWorker WorkerRunnable实际为一个Callback接口的包装类,在callback的基础上封装了可传入的参数
-
初始化mFuture FutureTask实际是一个Runnable和Future接口的实现类,通过Future的包装使得Runnable在完成后可以返回一个结果
- 接着是excute()函数
@MainThread public final AsyncTask<Params, Progress, Result> execute(Params... params) { return executeOnExecutor(sDefaultExecutor, params); } @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: 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; }
可以看到,execute函数是在必须在主线程中被调用的,这个函数实际调用的是executeOnExecutor函数, 在executeOnExecutor函数中,onPreExecute先被执行,然后是参数的赋值操作,最后是通过excutor来执行mFuture, 切换到子线程中进行工作,excutor的实现者如下
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);
}
}
}
可以看到,这里的SerialExecutor会执行mFutrue的run方法,而mFuture的通过mFuture = new FutureTask
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);
}
}
这里的callback对象正是传入的worker对象,通过执行worker的call方法,正式调用了doInBackground和postResult函数, doInBackground会在这个子线程中执行耗时任务,而postResult则是通过InternalHandler来发送一个Message消息为MESSAGE_POST_PROGRESS给主线程,通知进行UI更新也就是执行onProgressUpdate函数, 当任务执行完毕后,以同样的方式来通过MESSAGE_POST_RESULT消息来通知结果,最后,在finish函数中执行onPostExecute函数。
总结:
AsyncTask的内部封装了两个线程池(SerialExecutor和THREAD_POOL_EXECUTOR)和一个Handler(InternalHandler)。 整体的逻辑是,SerialExecutor线程池用于任务的排队,让需要执行的多个耗时任务,按顺序排列,用来保证任务的串行性,THREAD_POOL_EXECUTOR线程池才真正地执行任务,InternalHandler用于从工作线程切换到主线程。 另,默认情况下AsyncTask的执行效果是串行的,因为有了SerialExecutor类来维持保证队列的串行。如果想使用并行执行任务,那么可以直接跳过SerialExecutor类,使用executeOnExecutor()来执行任务。
注意
非静态AsyncTask创建时会默认持有一个Activity或者Fragment的引用,所以务必在onDestory中手动调用cancel(boolean)方法来释放,防止内存泄漏