AsyncTask
# 1. Asynctask简介
除了使用Handler实现线程间通信外,Android提供了一个工具类:AsyncTask,它使创建需要与用户界面交互的长时间运 行的任务变得更简单。在没有AsyncTask之前,使用Handler + Thread实现异步任务。相对来说AsyncTask更轻量级一些,适用于简单的异步处理,AsyncTask是对Handler和Thread的封装,封装了ThreadPool,效率更高。
# 相关API
AsyncTask是抽象类。AsyncTask定义了三种泛型类型Params
,Progress
和 Result
- Params启动任务执行的输入参数,比如,HTTP请求的URL
- Progress后台任务执行的百分比
- Result后台执行任务最终返回的结果,比如String
execute(Params...params)
- 启动任务,开始任务的执行流程
void onPreExecute()
- 在分线程工作开始之前在 UIThread 中执行,一般用来显示提示视图
Result dolnBackground(Params... params)
- 在 workerThread 中执行,完成任务的主要工作,通常需要较长的时间
void onPostExecute(Result result)
- 在dolnBackground()执行完后在 UIThread 中执行,一般用来更新界面
publishProgress(Progress...values):在分线程中,发布当前进度
void onProgressUpdate(Progress...values):在主线程中更新进度
// MyAsyncTask(this).execute()
private inner class MyAsyncTask : AsyncTask<String?, Int?, String?>() {
// 执行任务之前触发的事件方法,可以在该方法中作一些初始化工作
override fun onPreExecute() {
super.onPreExecute()
}
/**
* 类似于在线程中执行任务,不能访问UI组件
* @param params Array<out String?>
* @return String?
*/
override fun doInBackground(vararg params: String?): String? {
publishProgress(1) // 进度变化,onProgressUpdate会更新
return null
}
/**
* 更新进度值
* @param values Array<out Int?>
*/
override fun onProgressUpdate(vararg values: Int?) {
super.onProgressUpdate(*values)
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
AsyncTask 的泛型类型 异步任务使用的三种类型如下: Params ,执行时发送到任务的参数类型。 Progress ,后台计算期间发布的进度单元的类型。 Result ,后台计算Result的类型。 并非所有类型总是由异步任务使用。 要将类型标记为未使用,只需使用类型Void : private class MyTask extends AsyncTask<Void, Void, Void> { ... }
4个步骤 当一个异步任务被执行时,任务会经过 4 个步骤: onPreExecute() ,在执行任务之前在 UI 线程上调用。 此步骤通常用于设置任务,例如通过在用户界面中显示进度条。 doInBackground ,在onPreExecute()完成执行后立即在后台线程上调用。 此步骤用于执行可能需要很长时间的后台计算。 异步任务的参数传递到这一步。 计算的结果必须由这一步返回,并将传递回最后一步。 这一步也可以使用publishProgress来发布一个或多个进度单元。 这些值发布在 UI 线程上的onProgressUpdate步骤中。 onProgressUpdate ,在调用publishProgress后在 UI 线程上调用。 执行的时间是不确定的。 此方法用于在后台计算仍在执行时在用户界面中显示任何形式的进度。 例如,它可用于动画进度条或在文本字段中显示日志。 onPostExecute ,在后台计算完成后在 UI 线程上调用。 后台计算的结果作为参数传递给这一步。 取消任务 可以通过调用cancel(boolean)任务。 调用此方法将导致后续调用isCancelled()返回 true。 调用此方法后, onCancelled(Object) ,而不是onPostExecute(Object)之后将被调用doInBackground(Object[])的回报。 为了确保尽快取消任务,您应该始终定期从doInBackground(Object[])定期检查isCancelled()的返回值,如果可能的话(例如在循环中。) 线程规则 要使此类正常工作,必须遵循一些线程规则: AsyncTask 类必须在 UI 线程上加载。 这是从Build.VERSION_CODES.JELLY_BEAN自动完成的。 任务实例必须在 UI 线程上创建。 execute必须在 UI 线程上调用。 不要手动调用onPreExecute() 、 onPostExecute 、 doInBackground 、 onProgressUpdate 。 任务只能执行一次(如果尝试第二次执行,将抛出异常。) 内存可观察性 AsyncTask 保证所有回调调用都是同步的,以确保以下没有显式同步。 onPreExecute的内存影响,以及在调用execute之前执行的任何其他操作,包括 AsyncTask 对象的构造,对doInBackground都是可见的。 的记忆效应doInBackground是可见的onPostExecute 。 的任何记忆效应doInBackground到呼叫前publishProgress是到对应的可见onProgressUpdate呼叫。 (但doInBackground继续运行,需要注意doInBackground中的后续更新不会干扰正在进行的onProgressUpdate调用。) 呼叫前述任记忆效应cancel到呼叫后是可见的isCancelled ,则返回true,结果,或期间和所得到的呼叫后onCancelled 。 执行顺序 首次引入时,AsyncTasks 在单个后台线程上串行执行。 从Build.VERSION_CODES.DONUT开始,这被更改为允许多个任务并行操作的线程池。 从Build.VERSION_CODES.HONEYCOMB开始,任务在单个线程上执行,以避免并行执行导致的常见应用程序错误。 如果你真的想要并行执行,你可以用THREAD_POOL_EXECUTOR调用executeOnExecutor(Executor, Object[]) 。 已弃用 请改用标准的java.util.concurrent或Kotlin 并发实用程序 。