AsyncTask的简单使用
功能:实现工作线程 & 主线程(UI
线程)之间的通信,即:将工作线程的执行结果传递给主线程,从而在主线程中执行相关的UI
操作。在使用AsyncTask时,我们无需关注Thread和Handler,AsyncTask内部会对其进行管理,这样我们就只需要关注于我们的业务逻辑即可。
属于抽象类,即使用时需 实现子类
public abstract class AsyncTask<Params, Progress, Result> {}
参数介绍
Params: 开始异步任务执行时传入的参数类型(doInBackground()):
protected abstract Result doInBackground(Params... params);
对应excute()中传递的参数:
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);
}
Progress:异步任务执行过程中,返回下载进度值的类型,对应onProgressUpdate函数传入的参数类型
protected void onProgressUpdate(Progress... values) {}
Result:异步任务执行完成后,返回的结果类型对应onPostExecute方法传入的参数类型,并且与doInBackground()的返回值类型保持一致
protected void onPostExecute(Result result) { }
如下图所示:
AsyncTask
核心 & 常用的方法如下:
-
AsyncTask
的使用步骤有3个:
- 创建
AsyncTask
子类 & 根据需求实现核心方法 - 创建
AsyncTask
子类的实例对象(即 任务实例) - 手动调用
execute()
从而执行异步线程任务
/**
* 步骤1:创建AsyncTask子类
* 注:
* a. 继承AsyncTask类
* b. 为3个泛型参数指定类型;若不使用,可用java.lang.Void类型代替
* c. 根据需求,在AsyncTask子类内实现核心方法
*/
private class MyTask extends AsyncTask<Params, Progress, Result> {
....
/** 方法1:onPreExecute()
*作用:执行 线程任务前的操作
*这个方法会在后台任务开始执行之间调用,用于进行一些界面上的初始化操作,比如显示一个进度
*条对话框等。*/
@Override
protected void onPreExecute() {
...
}
/** 方法2:doInBackground()
*作用:接收输入参数、执行任务中的耗时操作、返回 线程任务执行的结果
*必须复写,从而自定义线程任务这个方法中的所有代码都会在子线程中运行,我们应该在这里去处理
*所有的耗时任务。任务一旦完成就可以通过return语句来将任务的执行结果进行返回,如果
*AsyncTask的第三个泛型参数指定的是Void,就可以不返回任务执行结果。注意,在这个方法中是不
*可以进行UI操作的,如果需要更新UI元素,比如说反馈当前任务的执行进度,可以调用
*publishProgress(Progress...)方法来完成。
*/
@Override
protected String doInBackground(String... params) {
...// 自定义的线程任务
// 可调用publishProgress()显示进度, 之后将执行onProgressUpdate()
publishProgress(count);
return String;
}
/**
*作用:在主线程 显示线程任务执行的进度
* 当在后台任务中调用了publishProgress(Progress...)方法后,这个方法就很快会被调用,方法
* 中携带的参数就是在后台任务中传递过来的。在这个方法中可以对UI进行操作,利用参数中的数值
*就可以对界面元素进行相应的更新。
*/
@Override
protected void onProgressUpdate(Integer... progresses) {
...
}
/**
*作用:接收线程任务执行结果、将执行结果显示到UI组件
*当后台任务执行完毕并通过return语句进行返回时,这个方法就很快会被调用。返回的数据会作为参
*数传递到此方法中,可以利用返回的数据来进行一些UI操作,比如说提醒任务执行的结果,以及关闭
*掉进度条对话框等。
*/
@Override
protected void onPostExecute(String result) {
...// UI操作
}
/*方法5:onCancelled()
* 作用:将异步任务设置为:取消状态
*/
@Override
protected void onCancelled() {
...
}
}
/**
* 步骤2:创建AsyncTask子类的实例对象(即 任务实例)
* 注:AsyncTask子类的实例必须在UI线程中创建
*/
MyTask mTask = new MyTask();
/**
* 步骤3:手动调用execute(Params... params) 从而执行异步线程任务
* 注:
* a. 必须在UI线程中调用
* b. 同一个AsyncTask实例对象只能执行1次,若执行第2次将会抛出异常
* c. 执行任务中,系统会自动调用AsyncTask的一系列方法:onPreExecute() 、doInBackground()、onProgressUpdate() 、onPostExecute()
* d. 不能手动调用上述方法
*/
mTask.execute();
在使用AsyncTask
时有一些问题需要注意的:
AsyncTask的实例必须在主线程中创建。
- AsyncTask的execute方法必须在主线程中调用。
- onPreExecute()、onPostExecute(Result),、doInBackground(Params…) 和 onProgressUpdate(Progress…)这四个方法都是回调方法,Android会自动调用,我们不应自己调用。
- 对于一个AsyncTack的实例,只能执行一次execute方法,在该实例上第二次执行execute方法时就会抛出异常。
-
AsyncTask
不与任何组件绑定生命周期,在Activity
或Fragment
中使用AsyncTask
时,最好在Activity
或Fragment
的onDestory()
调用cancel(boolean)
; - 若
AsyncTask
被声明为Activity
的非静态内部类,当Activity
需销毁时,会因AsyncTask
保留对Activity
的引用 而导致Activity
无法被回收,最终引起内存泄露,使用建议AsyncTask
应被声明为Activity
的静态内部类 -
线程任务执行结果 丢失,当
Activity
重新创建时(屏幕旋转 /Activity
被意外销毁时后恢复),之前运行的AsyncTask
(非静态的内部类)持有的之前Activity
引用已无效,故复写的onPostExecute()
将不生效,即无法更新UI操作。(解决方法:在Activity
恢复时的对应方法 重启 任务线程) - Execute()和executeOnExecutor有何区别
Execute():这个函数让任务是以单线程队列方式或线程池队列方式运行,会让任务以后台单线程串行方式执行。
executeOnExecutor():这个方法通常和THREAD_POOL_EXECUTOR一起使用,允许多个任务在由AsyncTask管理的线程池中并行执行。new MyTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,5);
本文地址:https://blog.csdn.net/csj731742019/article/details/107450905