- CompoundButton 源码分析
- LinearLayout 源码分析
- SearchView 源码解析
- LruCache 源码解析
- ViewDragHelper 源码解析
- BottomSheets 源码解析
- Media Player 源码分析
- NavigationView 源码解析
- Service 源码解析
- Binder 源码分析
- Android 应用 Preference 相关及源码浅析 SharePreferences 篇
- ScrollView 源码解析
- Handler 源码解析
- NestedScrollView 源码解析
- SQLiteOpenHelper/SQLiteDatabase/Cursor 源码解析
- Bundle 源码解析
- LocalBroadcastManager 源码解析
- Toast 源码解析
- TextInputLayout
- LayoutInflater 和 LayoutInflaterCompat 源码解析
- TextView 源码解析
- NestedScrolling 事件机制源码解析
- ViewGroup 源码解析
- StaticLayout 源码分析
- AtomicFile 源码解析
- AtomicFile 源码解析
- Spannable 源码分析
- Notification 之 Android 5.0 实现原理
- CoordinatorLayout 源码分析
- Scroller 源码解析
- SwipeRefreshLayout 源码分析
- FloatingActionButton 源码解析
- AsyncTask 源码分析
- TabLayout 源码解析
3.2、核心方法
1、execute() 方法
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
/** AsyncTask 类的 execute 方法**/
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
//调用 executeOnExecutor 方法
return executeOnExecutor(sDefaultExecutor, params);
}当执行 execute 方法时,实际上是调用了 executeOnExecutor 方法。这里传递了两个参数,一个是 sDefaultExecutor,一个是 params。从上面的源码可以看出,sDefaultExecutor 其实是一个 SerialExecutor 对象,实现了串行线程队列。params 其实最终会赋给 doInBackground 方法去处理。
2、executeOnExecutor() 方法
//exec 执行 AsyncTask.execute() 方法时传递进来的参数 sDefaultExecutor,这个 sDefaultExecutor 其实就是 SerialExecutor 对象。默认是串行执行的
//若想变成并发执行 exec 可以传入 AsyncTask.THREAD_POOL_EXECUTOR。
public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
Params... params) {
//如果一个任务已经进入执行的状态,再执行就会抛异常。这就决定了一个 AsyncTask 只能执行一次
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)");
}
}
//一旦 executeOnExecutor 调用了就标记为运行状态
mStatus = Status.RUNNING;
//实际是调用子类里面的 onPreExecute
onPreExecute();
//将处理的参数类型赋值给 mWorker
mWorker.mParams = params;
//execute 是调用 SERIAL_EXECUTOR 的 execute,mFuture 就是之前 AsyncTask 构造初始化赋值的 FutureTask。
exec.execute(mFuture);
return this;
}
这里要说明一下,AsyncTask 的异步任务有三种状态
- PENDING 待执行状态。当 AsyncTask 被创建时,就进入了 PENDING 状态。
- RUNNING 运行状态。当调用 executeOnExecutor,就进入了 RUNNING 状态。
- FINISHED 结束状态。当 AsyncTask 完成(用户 cancel() 或任务执行完毕) 时,就进入了 FINISHED 状态。
3、SerialExecutor 的 execute 方法
private static class SerialExecutor implements Executor {
//循环数组实现的双向 Queue。大小是 2 的倍数,默认是 16。有队头队尾两个下标
final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
//当前正在运行的 runnable
Runnable mActive;
public synchronized void execute(final Runnable r) {
//添加到双端队列里面去
mTasks.offer(new Runnable() {
public void run() {
try {
//执行的是 mFuture 就是之前 AsyncTask 构造初始化赋值的 FutureTask 的 run() 方法
r.run();
} finally {
//无论执行结果如何都会取出下一个任务执行
scheduleNext();
}
}
});
//如果没有活动的 runnable,从双端队列里面取出一个 runnable 放到线程池中运行
//第一个请求任务过来的时候 mActive 是空的
if (mActive == null) {
//取出下一个任务来执行
scheduleNext();
}
}
protected synchronized void scheduleNext() {
//从双端队列中取出一个任务
if ((mActive = mTasks.poll()) != null) {
//线程池执行取出来的任务,真正执行任务的
THREAD_POOL_EXECUTOR.execute(mActive);
}
}
}//javaexec.execute(mFuture) 执行时,SerialExecutor 将 FutureTask 作为参数执行 execute 方法。在 execute 方法中,假设 FutureTask 插入进了两个以上的任务队列到 mTasks 中,第一次过来 mActive==null ,通过 mTasks.poll() 取出一个任务丢给线程池运行,线程池执行 r.run,其实就是执行 FutureTask 的 run 方法,因为传递进来的 r 参数就是 mFuture。等到上一个线程执完 r.run() 完之后,这里是通过一个 try-finally 代码块,并在 finally 中调用了 scheduleNext() 方法,保证无论发生什么情况,scheduleNext() 都会取出下一个任务执行。
接着因为 mActive 不为空了,不会再执行``scheduleNext()`,由于存在一个循环队列,每个 Runnable 被执行的时候,都进入去队列,然后在执行完后出队,才会进入下一个 Runnable 的执行流程。由此可知道这是一个串行的执行过程,同一时刻只会有一个线程正在执行,其余的均处于等待状态。
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);//调用子类的 doInBackground
Binder.flushPendingCommands();
return postResult(result);//执行完后通过 postResult 结果传递出去
}
};上文中提到调用 call() 的流程: SerialExecutor.execute() -> FutureTask.run() -> WorkerRunnable.call() 如果回调了 call() 方法,就会调用了 doInBackground(mParams) 方法,这都是在子线程中执行的。执行完后,将结果通过 postResult(result) 发送出去。
4、AsyncTask 的 postResult 方法
private Result postResult(Result result) {
@SuppressWarnings("unchecked")
//获取一个 handler,等到一个消息,将结果封装在 Message
Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
new AsyncTaskResult<Result>(this, result));//new AsyncTaskResult<Result>(this, result) 将得到的结果再做了一层封装
//将消息发送到主线程,会回调 handleMessage() 方法
message.sendToTarget();
return result;
}
因为 postResult(Result result) 还是在子线程中调用的,如果要发送给主线程,必须通过 Handler。源码中使用 sHandler 并带着 MESSAGE_POST_RESULT 和封装了任务执行结果的对象 AsyncTaskResult,然后 message.sendToTarget() 开始发消息。
private static Handler getHandler() {
synchronized (AsyncTask.class) {
if (sHandler == null) {
//初始化一个 InternalHandler,用与将结果发送给主线程
sHandler = new InternalHandler();
}
return sHandler;
}
}并在 InternalHandler 的 handleMessage 中开始处理消息,InternalHandler 的源码如下所示:
private static class InternalHandler extends Handler {
public InternalHandler() {
// 这个 handler 是关联到主线程的
super(Looper.getMainLooper());
}
@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 消息,就会去执行 finish() 方法,
finish()源码如下文所示:
private void finish(Result result) {
if (isCancelled()) {
onCancelled(result);
} else {
onPostExecute(result);
}
mStatus = Status.FINISHED;
} 如果任务已经取消了,调用 onCancelled 方法,如果没被取消,则调用 onPostExecute() 方法。
- 如果
doInBackground(Void... params)调用publishProgress()方法,实际就是发送一条 MESSAGE_POST_PROGRESS 消息,就会去执行 onProgressUpdate() 方法。publishProgress()的源码如下文所示:
@WorkerThread
protected final void publishProgress(Progress... values) {
if (!isCancelled()) {
getHandler().obtainMessage(MESSAGE_POST_PROGRESS,
new AsyncTaskResult<Progress>(this, values)).sendToTarget();
}
}如果你还不够清晰,请看下面的这个流程图。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!

发布评论