AsyncTask 源码解析
AsyncTask 是 Android 提供的轻量级异步任务类,用于在后台线程中执行任务,并在完成后更新主线程(UI)。虽然在 Android API 30 中已被标记为 Deprecated,但它在早期项目中仍被广泛使用。
AsyncTask 使用方法
典型使用示例:
java
复制代码
class MyTask extends AsyncTask<String, Integer, String> {
@Override
protected void onPreExecute() {
// 主线程:任务开始前的准备
super.onPreExecute();
}
@Override
protected String doInBackground(String... params) {
// 后台线程:执行耗时操作
for (int i = 0; i < 100; i++) {
publishProgress(i); // 更新进度
}
return "Result";
}
@Override
protected void onProgressUpdate(Integer... values) {
// 主线程:更新进度
super.onProgressUpdate(values);
}
@Override
protected void onPostExecute(String result) {
// 主线程:任务执行完成
super.onPostExecute(result);
}
}
调用:
java
复制代码
new MyTask().execute("Task Parameter");
AsyncTask 工作流程
-
主线程中调用
execute():- 启动任务,创建异步线程。
- 触发
onPreExecute(),表示任务开始。
-
doInBackground():- 在工作线程中运行,执行耗时操作。
-
进度更新:
- 调用
publishProgress()在工作线程中更新进度。 - 触发
onProgressUpdate()在主线程中更新 UI。
- 调用
-
任务完成:
- 执行结束后调用
onPostExecute()返回结果到主线程。
- 执行结束后调用
AsyncTask 核心源码分析
1. execute() 方法
调用 execute() 方法时,AsyncTask 会启动任务。
源码(简化):
java
复制代码
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);
}
- 默认使用
SerialExecutor(串行执行)。 - 调用
executeOnExecutor()。
2. executeOnExecutor()
源码(简化):
java
复制代码
public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec, Params... params) {
if (mStatus != Status.PENDING) {
throw new IllegalStateException("Task already executed");
}
mStatus = Status.RUNNING;
// 触发 onPreExecute()
onPreExecute();
// 提交任务到线程池
mWorker.mParams = params;
exec.execute(mFuture);
return this;
}
onPreExecute():执行任务前的准备工作。exec.execute(mFuture):将任务提交到线程池。
3. 后台任务执行
工作线程:mWorker
mWorker 是 Callable,其核心是 doInBackground()。
源码(简化):
java
复制代码
private final WorkerRunnable<Params, Result> mWorker = new WorkerRunnable<Params, Result>() {
public Result call() throws Exception {
mTaskInvoked.set(true);
Result result = doInBackground(mParams);
Binder.flushPendingCommands();
return postResult(result);
}
};
doInBackground():在后台线程中执行任务。postResult(result):处理任务结果。
线程池:mFuture
mFuture 是 FutureTask,负责调度任务。
源码(简化):
java
复制代码
private final FutureTask<Result> mFuture = new FutureTask<Result>(mWorker) {
@Override
protected void done() {
try {
postResultIfNotInvoked(get());
} catch (InterruptedException | ExecutionException e) {
throw new RuntimeException("An error occurred while executing doInBackground()", e);
}
}
};
get():阻塞获取doInBackground()的返回结果。postResultIfNotInvoked():将结果传递给主线程。
4. 结果回调
任务结果通过 postResult() 回调。
源码(简化):
java
复制代码
private Result postResult(Result result) {
Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT, new AsyncTaskResult<>(this, result));
message.sendToTarget();
return result;
}
- 创建
Message,将结果发送到主线程的Handler。
5. 主线程 Handler
Handler 处理消息
主线程通过 Handler 分发消息。
源码(简化):
java
复制代码
private static class InternalHandler extends Handler {
@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;
}
}
}
MESSAGE_POST_RESULT:调用onPostExecute()。MESSAGE_POST_PROGRESS:调用onProgressUpdate()。
6. 串行与并行执行
串行执行(默认)
使用 SerialExecutor 串行执行任务。
java
复制代码
private static class SerialExecutor implements Executor {
final ArrayDeque<Runnable> mTasks = new ArrayDeque<>();
Runnable mActive;
@Override
public synchronized void execute(final Runnable command) {
mTasks.offer(() -> {
try {
command.run();
} finally {
scheduleNext();
}
});
if (mActive == null) {
scheduleNext();
}
}
protected synchronized void scheduleNext() {
if ((mActive = mTasks.poll()) != null) {
THREAD_POOL_EXECUTOR.execute(mActive);
}
}
}
- 将任务放入队列,按顺序执行。
并行执行
通过 THREAD_POOL_EXECUTOR 并行执行任务。
java
复制代码
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, params);
AsyncTask 的局限性
-
内存泄漏:
- 异步任务持有外部类引用,可能导致内存泄漏。
-
任务队列限制:
- 默认串行执行,容易造成阻塞。
-
生命周期问题:
- 任务在 Activity/Fragment 销毁后可能仍在运行,导致崩溃。
AsyncTask 的替代方案
-
HandlerThread:
- 更灵活的后台任务执行方式。
-
ThreadPoolExecutor:
- 高效的线程池管理。
-
RxJava:
- 支持复杂异步任务链。
-
Kotlin Coroutines:
- 使用
suspend和Flow提供现代异步编程解决方案。
- 使用
总结
AsyncTask 是一个简单的异步任务工具,核心是通过 线程池(线程调度) 和 主线程 Handler 实现异步任务的执行和结果回调。尽管它在现代 Android 开发中已被淘汰,但对其原理的理解有助于更好地掌握 Android 异步编程模型。
如果需要更强大的异步任务能力,推荐使用 RxJava 或 Kotlin Coroutines。