介绍
AsyncTask是一个轻量级的异步任务类,它可以在线程池中执行任务,然后把结果和执行进度传递到主线程并在主线程更新UI。内部实现封装了Thread和Handler,可以方便的执行后台任务以及主线程中访问UI,但是AsyncTask并不适合执行特别耗时的操作,耗时操作建议使用线程池。
核心方法
AsyncTask是一个抽象的泛型类提供了三个泛型参数<Params,Progress,Result>,Params表示参数的类型,Progress表示运行的进度,Result表示运行结束后返回的结果类型。
主要提供可以下四个核心方法:
1.onPreExecute(),在主线程中执行,在异步任务以前,主要做一些准备工作
2.doInBackground(Params... params),在线程池中工作,params是传递进来的参数,在这个方法中可以通过publicProgress方法来更新进度,public会调用onProgressUpdate方法来更新进度。这个方法需要返回计算结果返回给onPostExecute方法
3.onProgressUpdate(Progress progress),这个方法运行在UI线程中,用来更新进度
4.onPostExecute(Result result),运行在主线程中,doInBackground运行完成后会调用此方法,result既是是doInBackground返回的结果
使用方式和注意
1.一个asynctask对象只能执行一次,如果多次调用一个对象会报 Cannot execute task: the task is already running.异常
2.使用execute()运行AsyncTask,3.0(API 11)以后默认是串行执行任务。也可以通过executeOnExecutor方法并行执行任务,可以根据不同需求传递通过executeOnExecutor(Executor exec,Params... params)构造方法传递一个Executor 设置线程池并行的数量,如下图:设置固定5个线程的线程池,只有前5个任务执行完毕后,最后两个线程才会执行
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_asynctask);
newFixedExecutor = Executors.newFixedThreadPool(5);//设置固定5个线程的线程池
myAsyncTask =new MyAsyncTask();
myAsyncTask2 =new MyAsyncTask();
myAsyncTask3 =new MyAsyncTask();
myAsyncTask4 =new MyAsyncTask();
myAsyncTask5 =new MyAsyncTask();
myAsyncTask6 =new MyAsyncTask();
myAsyncTask7 =new MyAsyncTask();
}
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
myAsyncTask.executeOnExecutor(newFixedExecutor ,mProgressBar);
myAsyncTask2.executeOnExecutor(newFixedExecutor ,mProgressBar2);
myAsyncTask3.executeOnExecutor(newFixedExecutor ,mProgressBar3);
myAsyncTask4.executeOnExecutor(newFixedExecutor ,mProgressBar4);
myAsyncTask5.executeOnExecutor(newFixedExecutor ,mProgressBar5);
myAsyncTask6.executeOnExecutor(newFixedExecutor ,mProgressBar6);
myAsyncTask7.executeOnExecutor(newFixedExecutor ,mProgressBar7);
}
});
Screenshot_20180828-112340.jpg
Screenshot_20180828-112349.jpg
3.AsyncTask不适合执行特别耗时的操作,耗时操作建议使用线程池来完成
4.AsyncTask一般都说只能在主线程中调用,但是在API 26下,看AsyncTask源码其实也可以在子线程中调用,因为在初始化Handler时已经将主线程的Looper传递Handler(如下图代码),这样消息仍然可以传递给主线程。其他以前版本源码没有看过,但是能不能在其他线程中运行,就看源码中是否传递的Looper是当前线程的还是getMainLooper(),如果是getMainLooper,那么在其他线程运行应该就没问题。
private static Handler getMainHandler() {
synchronized (AsyncTask.class) {
if (sHandler == null) {
sHandler = new InternalHandler(Looper.getMainLooper());
}
return sHandler;
}
}
AsyncTask版本演进
1.在1.6之前,AsyncTask是串行执行任务
2.在1.6的时候,AsyncTask开始采用线程池处理并行任务
3.但是从3.0开始为了避免AsyncTask所带来的并发错误,AsyncTask又采用一个线程来串行执行任务,但是仍然可以通过executeOnExecutor方法来并行执行任务
参考
1.《Android开发艺术开发探索》任玉刚
网友评论