AsyncTask已经被正式弃用了,但是很多app还是在用它的,所以还是要看下它的用法,谷歌建议使用java.util.concurrent
or Kotlin concurrency utilities 这俩替代
震惊!AsyncTask将被弃用?_rqX的博客-CSDN博客_asynctask被弃用
弃用的原因可以看看上面的博文
作用
- 实现多线程:在工作线程中执行任务,如 耗时任务
- 异步通信、消息传递:实现工作线程 & 主线程(
UI
线程)之间的通信,即:将工作线程的执行结果传递给主线程,从而在主线程中执行相关的UI
操作,保证线程安全。
比如,适用于子线程执行耗时操作并且需要有一个结果返回给主线程,这个时候我们就可以用AsyncTask实现.
AsyncTask其实就是把Thread进行了封装,内部实现原理还是Thread+Handler
基本使用
1.继承抽象类AsyncTask类并指定泛型,根据需求实现/重写该类的方法.
AsyncTask<Params, Progress, Result>
//我这里的泛型用的Void, Void, Boolean,当然根据需要自己选别的用
private class MyTask extends AsyncTask<Void, Void, Boolean> {
....
// 方法1:onPreExecute()
// 作用:执行 线程任务前的操作
// 注:根据需求复写
@Override
protected void onPreExecute() {
...
}
// 方法2:doInBackground()
// 作用:接收输入参数、执行任务中的耗时操作、返回 线程任务执行的结果
// 注:必须复写,从而自定义线程任务
@Override
protected Boolean doInBackground(Void... params) {
...// 自定义的线程任务
// 可调用publishProgress()显示进度, 之后将执行onProgressUpdate()
publishProgress(count);
}
// 方法3:onProgressUpdate()
// 作用:在主线程 显示线程任务执行的进度
// 注:根据需求复写
@Override
protected void onProgressUpdate(Void... progresses) {
...
}
// 方法4:onPostExecute()
// 作用:接收线程任务doInBackground()的执行结果、将result显示到UI组件
// 注:必须复写,从而自定义UI操作
@Override
protected void onPostExecute(Boolean result) {
...// UI操作
}
// 方法5:onCancelled()
// 作用:被调用cancel()之后,会走到这个函数而不是onPostExecute函数
@Override
protected void onCancelled(Boolean result) {
...
}
}
注意 这里面函数的传参要跟我们继承的类的参数类型保持一致.
2. 调用execute或者executeOnExecutor方法
MyTask mTask = new MyTask();
mTask.execute(); //mTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
区别在于后者用到了线程池。
3. cancel()方法的作用
不要以为调用了mTask.cancel(true)就可以直接取消线程了,实际上是不可以的,这个方法只相当于置一个标志位给mTask,而调用了cancel之后, 我们可以在doInBackground中用isCancelled()判断.
举个例子
@Override
protected Boolean doInBackground(Void... params) {
.....
if (isCancelled()){
result = false;
return result;
}
//做一些耗时操作
dosomething();
return .....
}
就是说,我们可以通过sCancelled()判断是否cancel被调用,如果被调用,那么就对result做一些措施,
需要根据我们自己想要实现的东西来放判断的位置和具体措施.
上面代码就是耗时前判断一次,要是耗时前就被调用cancel那很好,直接不用做耗时操作了,return掉.
然后我们在继承AsyncTask类里面重写的onCancelled()方法就有用了,因为cancel了之后retun之后不会再调用onPostExecute( ),而是会调用onCancelled()
问题讨论
别再傻傻得认为AsyncTask只可以在主线程中创建实例和调用execute方法_smileiam的专栏-CSDN博客
总结一下就是,可以在子线程中创建AsyncTask实例,并执行execute. 注意在哪个线程执行AsyncTask的execute(),onPreExecute会运行在执行在哪个线程中,onPostExecute方法还是会执行在主线程中,doInBackground方法会执行在AsyncTask创建的线程中。
这个问题的核心是, Handler实例化需要用到线程的Looper,而我自己新建的Thread并没有调用Looper.prepare(),所以新开的线程Looper肯定为空,怎么会运行正常呢?
因为AsyncTask源码里Handler持有的主线程的Looper
sHandler = new InternalHandler(Looper.getMainLooper());