Android-知识-014-Android多线程-AsyncTask-源码解析

89 阅读3分钟

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 工作流程

  1. 主线程中调用 execute()

    • 启动任务,创建异步线程。
    • 触发 onPreExecute(),表示任务开始。
  2. doInBackground()

    • 在工作线程中运行,执行耗时操作。
  3. 进度更新:

    • 调用 publishProgress() 在工作线程中更新进度。
    • 触发 onProgressUpdate() 在主线程中更新 UI。
  4. 任务完成:

    • 执行结束后调用 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

mWorkerCallable,其核心是 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

mFutureFutureTask,负责调度任务。

源码(简化):

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 的局限性

  1. 内存泄漏

    • 异步任务持有外部类引用,可能导致内存泄漏。
  2. 任务队列限制

    • 默认串行执行,容易造成阻塞。
  3. 生命周期问题

    • 任务在 Activity/Fragment 销毁后可能仍在运行,导致崩溃。

AsyncTask 的替代方案

  1. HandlerThread

    • 更灵活的后台任务执行方式。
  2. ThreadPoolExecutor

    • 高效的线程池管理。
  3. RxJava

    • 支持复杂异步任务链。
  4. Kotlin Coroutines

    • 使用 suspendFlow 提供现代异步编程解决方案。

总结

AsyncTask 是一个简单的异步任务工具,核心是通过 线程池(线程调度)主线程 Handler 实现异步任务的执行和结果回调。尽管它在现代 Android 开发中已被淘汰,但对其原理的理解有助于更好地掌握 Android 异步编程模型。

如果需要更强大的异步任务能力,推荐使用 RxJavaKotlin Coroutines