【精华】Android面试精华总结——AsyncTask组件

一、AsyncTask简介

  为了避免UI线程失去响应的问题,Android建议将耗时操作放在新线程中完成,但新线程也可能需要动态更新UI组件,但新线程不允许直接更新UI组件。在Android的多线程编程当中,我们有两条非常重要的原则必须要遵守:

  1. 绝对不能在UI Thread当中进行耗时的操作,不能阻塞我们的UI Thread。
  2. 不能在UI Thread之外的线程当中操纵我们的UI元素。

  为了解决该问题,Android提供了如下实现多线程的方法:

  • 继承Thread类
  • 实现Runnable接口
  • Handler
  • AsyncTask
  • HandlerThread

  AsyncTask允许在后台执行一个异步任务。我们可以将耗时的操作放在异步任务当中来执行,并随时将任务执行的结果返回给我们的UI线程来更新我们的UI控件。通过AsyncTask我们可以轻松的解决多线程之间的通信问题。
  AsyncTask是Android提供的轻量级的异步类,查看源码发现其内部就是一个Handler和线程池的封装,其实现原理也是基于异步消息处理机制的,只是Android帮我们做好了封装。

二、作用和优点

1.作用

  • 实现多线程:在工作线程中执行任务,如 耗时任务。
  • 异步通信、消息传递:实现工作线程和主线程(UI线程)之间的通信,将工作线程的执行结果传递给主线程,从而在主线程中执行相关的UI操作。

2.优点

  • 方便实现异步通信:不需使用 “任务线程+ Handler”的复杂组合;
  • 节省资源:采用线程池的缓存线程 + 复用线程,避免了频繁创建和销毁线程所带来的系统资源开销。

三、AsyncTask类

  AsyncTask<Params,Progress,Result>是一个抽象类,通常用于被继承。继承AsyncTask需要指定如下三个泛型参数:

  • Params:启动任务时输入的参数类型;
  • Progress:后台任务执行中返回进度值的类型;
  • Result:后台任务执行完成后返回结果的类型。

  需要重写的AsyncTask方法:

  • doInBackground(Params...):必须重写,异步执行后台线程要完成的任务,耗时操作将在此方法中完成。
  • onPreExecute():执行后台耗时操作前被调用,通常用于进行初始化操作。
  • onPostExecute(Progress...):当doInBackground方法完成后,系统将自动调用此方法,并将doInBackground方法返回的值传入此方法,通过此方法进行UI的更新。
  • onProgressUpdate(Result):当在doInBackground方法中调用publishProgress方法更新任务执行进度后,将调用此方法,通过此方法可以知晓任务的完成进度。

  总结:在doInBackground()方法中执行具体的耗时任务,在onProgressUpdate()方法中进行UI操作,在onPostExecute()方法中执行一些任务的收尾工作。

在这里插入图片描述
  其他常用方法:

  • cancel (boolean mayInterruptIfRunning):尝试取消这个任务的执行。
  • execute (Params... params)用指定的参数来执行此任务(必须在UI线程中调用,因为要将handler绑定到主线程的Looper,方便后台任务执行完毕后,由后台线程切换到UI线程去更新UI)。
  • executeOnExecutor(Executor exec,Params... params):用指定的参数行此任务,并运行在指定的线程池中(必须在UI线程中调用)
  • getStatus():获得任务的当前状态:PENDING(等待执行)、RUNNING(正在运行)、FINISHED(运行完成)
  • isCancelled():在任务正常结束之前能成功取消任务则返回true,否则返回false

三、使用方法

  使用步骤:

  1. 新建内部类继承AsyncTask,并为三个泛型指定参数类型。若不需要指定类型指定为void。
  2. 根据需要实现AsyncTask的如下方法: doInBackground(Params…)、 onPreExecute()、 onPostExecute(Progress…)、onProgressUpdate(Result)。
  3. 调用AsyncTask子类实例的excute(Params…params)方法开始执行耗时任务。

  使用AsyncTask时必须遵循如下规则:
  1.必须在UI线程中创建AsyncTask的实例。
  2.必须在UI线程中调用AsyncTask的execute()方法。
  3.AsyncTask的doInBackground(Params...)、 onPreExecute()、 onPostExecute(Progress...)、onProgressUpdate(Result)方法,不应由程序员代码调用,而是由Android系统负责调用。
  4.每个AsyncTask只能被执行一次,多次调用将会引发异常。

/**
  * 步骤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()
      // 作用:接收输入参数、执行任务中的耗时操作、返回 线程任务执行的结果
      // 注:必须复写,从而自定义线程任务
      @Override
      protected String doInBackground(String... params) {

            ...// 自定义的线程任务

            // 可调用publishProgress()显示进度, 之后将执行onProgressUpdate()
             publishProgress(count);
              
         }

      // 方法3:onProgressUpdate()
      // 作用:在主线程 显示线程任务执行的进度
      // 注:根据需求复写
      @Override
      protected void onProgressUpdate(Integer... progresses) {
            ...

        }

      // 方法4:onPostExecute()
      // 作用:接收线程任务执行结果、将执行结果显示到UI组件
      // 注:必须复写,从而自定义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()

四、其他

1.AsyncTask与Handler的优缺点

  AsyncTask与Handler都是为了避免阻塞UI线程工作,都适用于简单的异步处理,相比之下AsyncTask更轻量级(代码上更轻量,实际更耗资源)。

  AsyncTask:

  • 优点:简单、快捷、过程可控。
  • 缺点:在使用多个异步操作并进行UI变更时,就会比较复杂。

  Handler:

  • 优点:结构清晰、功能定义明确。
  • 缺点:在单个后台异步处理时显得代码过多,结构过于复杂。
发布了123 篇原创文章 · 获赞 119 · 访问量 9万+

猜你喜欢

转载自blog.csdn.net/cbwem/article/details/90139976