在讲源码之前还是习惯性的把demo拿出来写一写:
static class MyAsyncTask extends AsyncTask<Void, Integer, Boolean> {
int progress;
ProgressBar progressBar;
MyAsyncTask(ProgressBar progressBar) {
this.progressBar = progressBar;
}
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected Boolean doInBackground(Void... voids) {
while (progress < 100) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
progress++;
publishProgress(progress);
}
return true;
}
@Override
protected void onPostExecute(Boolean aBoolean) {
super.onPostExecute(aBoolean);
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
progressBar.setProgress(values[0]);
}
}
调用的地方:
new MyAsyncTask(progressBar).execute();
demo的源代码是在android-28下面的,android studio没有集成28的源码,赶快集成起来吧,这里主要分析onPreExecute
、doInBackground
、onPostExecute
、onProgressUpdate
等方法主要发生的地方。
源码分析:
image.pngAsyncTask是一个抽象类,并且需要指明三个参数的类型,分别是Params、Progress、Result,接着看下AsyncTask构造方法都做了些啥:
/**
* Creates a new asynchronous task. This constructor must be invoked on the UI thread.
*/
public AsyncTask() {
this((Looper) null);
}
/**
* Creates a new asynchronous task. This constructor must be invoked on the UI thread.
*
* @hide
*/
public AsyncTask(@Nullable Handler handler) {
this(handler != null ? handler.getLooper() : null);
}
/**
* Creates a new asynchronous task. This constructor must be invoked on the UI thread.
*
* @hide
*/
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);
}
}
};
}
从上面可以看到调用的是第三个hide类型的构造方法:
从mHandler的初始化就可以看出来,咋们的handler获取的是getMainHandler
private static Handler getMainHandler() {
synchronized (AsyncTask.class) {
if (sHandler == null) {
sHandler = new InternalHandler(Looper.getMainLooper());
}
return sHandler;
}
}
创建了一个InternalHandler
,并且将mainLooper传了进去:
private static class InternalHandler extends Handler {
public InternalHandler(Looper looper) {
super(looper);
}
@SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})
@Override
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;
}
}
}
其实就是我们经常写的Handler,这里封装了两种状态,稍后再说该Handler处理的逻辑,咋们还是回到构造函数的创建那,分别创建了一个WorkerRunnable
对象和FutureTask
变量,WorkerRunnable
是一个Callable
对象,FutureTask
是一个RunnableFuture
对象,是Runnable
和Future
对象的结合:
image.png
image.png
其实可以看出来他两的代码
WorkerRunnable
是一个工作的子线程,类似平常写的runnable功能,FutureTask
也是一个WorkerRunnable
,用来处理WorkerRunnable
。因为我们可以从FutureTask
看出来,把mWorker
对象传给了FutureTask
的构造器,后面再细说FutureTask
是怎么工作的,以及怎么处理WorkerRunnable
的,下面我们直接看AsyncTask
的execute
方法:
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);
}
直接调用了executeOnExecutor
方法,并且把sDefaultExecutor
传过去了,sDefaultExecutor
它是一个SerialExecutor
对象。它是一个Executor
对象,也就是java中提供的线程池:
先不做过多的该类分析,接着看executeOnExecutor
方法:
@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;
}
先是状态的判断,可以看到第一次调用excute方法会将状态至为RUNNING,多次再调用excute方法会抛异常。
紧接着调用了onPreExecute
方法,所以明白为啥onPreExecute
是异步任务之前重写的方法,该方法是个空的实现:
然后将传进来的params给了mWorker对象,下面看下
exec.execute(mFuture)
方法做了些啥,上面已经知道exec
是一个SerialExecutor
对象,执行的任务是mFuture
,看看SerialExecutor
中excute
怎么执行mFuture
的:
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 {
//mFuture的run方法
r.run();
} finally {
scheduleNext();
}
}
});
if (mActive == null) {
scheduleNext();
}
}
protected synchronized void scheduleNext() {
if ((mActive = mTasks.poll()) != null) {
THREAD_POOL_EXECUTOR.execute(mActive);
}
}
}
这里用到了ArrayDeque
对象,看名字就知道有点类似ArrayList的功能,没错它就是一个集合,excute里面添加任务到mTasks
里面,然后在scheduleNext
里面先是判断mActive
是不是空的,可以看出来刚开始的时候,mTasks.poll()
是空的对象,因此只有当调用了offer方法后,才能保证任务不是空的。因此可以看出来只有当mTasks有任务的时候,才能保证该任务被THREAD_POOL_EXECUTOR所执行,也保证了只有一个任务在执行,这个是SerialExecutor
的职责,分析完了SerialExecutor
是怎么工作的,下面到传进来的mFuture
的run
方法中看看了:
public void run() {
if (state != NEW ||
!U.compareAndSwapObject(this, RUNNER, null, Thread.currentThread()))
return;
try {
//1.callable对象是传进来的mWorker对象
Callable<V> c = callable;
if (c != null && state == NEW) {
V result;
boolean ran;
try {
//2.调用了mWorker对象的call方法
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);
}
}
看到注释1和注释2没,其实这里就是调用了AsyncTask
类中的mWorker
对象的call
方法,再看下该方法:
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;
}
};
终于到了我们熟悉的影子了,doInBackground
方法是在该处被触发的,在finally
里面调用了postResult
方法:
private Result postResult(Result result) {
@SuppressWarnings("unchecked")
Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
new AsyncTaskResult<Result>(this, result));
message.sendToTarget();
return result;
}
看到了没,这里有我们熟悉的handler的使用,并且发送的what值是MESSAGE_POST_RESULT
,那咱们看下上面提到的InternalHandler
:
@SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})
@Override
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;
}
}
此处当MESSAGE_POST_RESULT
的时候,调用了AsyncTask
的finish
方法:
private void finish(Result result) {
if (isCancelled()) {
onCancelled(result);
} else {
onPostExecute(result);
}
mStatus = Status.FINISHED;
}
很熟悉了吧,这里直接调用了onPostExecute
方法,并且把状态改成finish状态。在我们的demo中调用了publishProgress
方法:
protected final void publishProgress(Progress... values) {
if (!isCancelled()) {
getHandler().obtainMessage(MESSAGE_POST_PROGRESS,
new AsyncTaskResult<Progress>(this, values)).sendToTarget();
}
}
也是通过handler发送了what= MESSAGE_POST_PROGRESS的消息,所以直接看到handler里面触发了AsyncTask
的onProgressUpdate
方法。整个过程基本是这样的,关于线程池没过多的分析,只针对它的excuse方法执行Runnable的run方法。
总结
AsyncTask首先会创建两个任务,一个是WorkerRunnable
,一个是FutureTask
,其中FutureTask
是专门处理WorkerRunnable
的,WorkerRunnable
是真正处理子线程的任务。默认会创建一个SerialExecutor
的线程池,以及ThreadPoolExecutor
线程池,SerialExecutor
的任务是将FutureTask
惊醒包装放到自己的ArrayDeque
队列里面,每次在取的时候,先要保证offer过了,才能取出该任务,并且该线程池保证了只有一个任务在执行,最后将ArrayDeque
里面的Runnable
交给了ThreadPoolExecutor
线程池。所以说真正处理任务的还是ThreadPoolExecutor
线程池。任务处理完了后,交给了Handler处理,Handler一共处理两种情况,一种是任务执行完了,一种是进度的改变,最后交给了onPostExecute
方法。
网友评论