AsyncTask使用方式和版本演进

介绍

AsyncTask是一个轻量级的异步任务类,它可以在线程池中执行任务,然后把结果和执行进度传递到主线程并在主线程更新UI。内部实现封装了Thread和Handler,可以方便的执行后台任务以及主线程中访问UI,但是AsyncTask并不适合执行特别耗时的操作,耗时操作建议使用线程池。

核心方法

AsyncTask是一个抽象的泛型类提供了三个泛型参数,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开发艺术开发探索》任玉刚

  1. AsyncTask 坑(一) 哪些线程可以调用AsyncTask

  2. Android实战技巧:深入解析AsyncTask

你可能感兴趣的:(AsyncTask使用方式和版本演进)