Skip to content

AsyncTask 使用介绍

更新日期: 2021-9-11
  • 2021-9-11 更新
  • 2020-4-20 创建文档

deprecated 已不再推荐使用

在API 30中不再推荐使用AsyncTask。请使用java.util.concurrent中的方法,或者Kotlin协程。

本文简单介绍Android中的AsyncTask的用法。

AsyncTask有助于使用UI线程。这个类能让你不主动使用多线程或Handler,在子线程种执行耗时任务,并在UI线程发布结果。 AsyncTask是一个在不需要开发者直接操作多线程和Handler的情况下的帮助类,适用于短时间的操作(最多几秒)。 如需长时间的线程操作,建议使用多线程包java.util.concurrent中的功能,比如线程池

假设我们有个需要在后台线程中运行的异步计算任务,并且结果需要更新ui。 那我们需要关注3个范型参数:ParamsProgressResult。 再关注4个步骤方法:onPreExecute, doInBackground, onProgressUpdateonPostExecute

属性介绍

使用AsyncTask之前,我们先看一下它的三个类型。

AsyncTask<Params, Progress, Result>

  • Params 执行任务前,传入的参数的类型
  • Progress 后台线程执行的时候,用来表示进度的类型
  • Result 表示执行结果的类型

这3个类型需要开发者自己指定。比如指定 String, Integer 等。这3个类型在后面的方法里会用到。

不用的泛型可以用Void表示。例如

private class MyTask extends AsyncTask<Void, Void, Void> { ... }

方法介绍

要使用AsyncTask,必须新建一个类来继承它,并且重写doInBackground方法。通常也会重写onPostExecute方法。 执行异步任务的时候,我们主要关心下面这4个方法。

  • onPreExecute() 执行任务前在ui线程调用。通用用来设置任务,比如在界面上显示一个进度条。
  • Result doInBackground(Params... params)onPreExecute()结束后立即调用这个方法。耗时的异步任务就在这里操作。执行任务时传入的参数会被传到这里。异步任务的中间结果在这里可以用publishProgress发送到主线程。
  • onProgressUpdate(Progress... values) 在ui线程中执行。后台任务还在进行的时候,这里负责处理进度信息。比如在这显示进度条动画,修改文字显示等。
  • onPostExecute(Result result) 后台任务结束了调这个方法。它在ui线程执行。最后的结果会传到这。

用法示例

虚构一个计算任务

/**
 * 虚拟的计算任务
 */
private class CalculationTask extends AsyncTask<Float, Integer, Float> {
    protected Float doInBackground(Float... inputs) {
        Log.d(TAG, "doInBackground thread ID = " + Thread.currentThread().getId());
        long step = 0;
        float result = 0;
        for (float f : inputs) {
            // 假设这里有一些耗时的操作
            result += f;
        }
        while (step < 5) {
            result += step;
            step++;
            publishProgress((int) step);
        }
        return result;
    }

    protected void onProgressUpdate(Integer... progress) {
        Log.d(TAG, "onProgressUpdate thread ID = " + Thread.currentThread().getId());
        Log.d(TAG, "onProgressUpdate: " + progress[0]);
    }

    protected void onPostExecute(Float result) {
        Log.d(TAG, "onPostExecute thread ID = " + Thread.currentThread().getId());
        Log.d(TAG, "任务执行完毕");
    }
}

// 执行任务
new CalculationTask().execute(1.2f, 2.3f, 6.3f);

取消任务

调用cancel(boolean)可随时取消任务。取消任务后isCancelled()会返回true。 调用这个方法后,后台任务doInBackground(Object[])执行完毕后会调用onCancelled(Object)而不再是onPostExecute(Object)。 为保证任务能被及时地取消,在doInBackground(Object[])中应该经常检查isCancelled()返回值

线程规则 Threading rules

一些线程规则

  • 异步任务必须从UI线程启动
  • 必须在UI线程实例化AsyncTask类
  • 必须在UI线程调用execute(Params...)
  • 不要手动调用onPreExecute(), onPostExecute(Result), doInBackground(Params...), onProgressUpdate(Progress...)
  • 同一个异步任务实例只能被执行一次。重复执行同一个异步任务实例会抛出异常(IllegalStateException)。


参考:

作者: RustFisher
联系: rf.cs@foxmail.com
博客: rustfisher.com | RustFisher cnblog
示例: AndroidTutorial Gitee, Tutorial Github
链接: https://www.an.rustfisher.com/android/thread/async-task-use-intro/
一家之言,仅当抛砖引玉。如有错漏,还请指出。