前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >AsyncTask 相关问题

AsyncTask 相关问题

原创
作者头像
李林LiLin
修改2021-04-06 11:14:56
5300
修改2021-04-06 11:14:56
举报
文章被收录于专栏:Android进阶编程Android进阶编程

什么是AsyncTask

  1. AsyncTask内部封装了Thread和Handler,可以让我们在后台进行计算或者把计算的结果及时更新到UI上。
  2. AsyncTask的作用就是简化的Thread + Handler,让我们能够通过更少的代码来完成一样的功能。
  3. AsyncTask 是一个抽象的泛型类,它提供了 Params、Progress 和 Result 这三个 泛型参数,其中 Params 表示参数的类型,Progress 表示后台任务的执行进度和 类型,而 Result 则表示后台任务的返回结果的类型,如果 AsyncTask 不需要传 递具体的参数,那么这三个泛型参数可以用 Void 来代替。

AsyncTask原理

  1. AsyncTask 中 有 两 个 线 程 池 ( SerialExecutor 和 THREAD_POOL_EXECUTOR)和一个Handler(InternalHandler),其中 线程池 SerialExecutor 用于任务的排队,而线程池 THREAD_POOL_EXECUTOR 用于真正地执行任务,InternalHandler 用于将执行环境从线程池切换到主线程。
  2. sHandler 是一个静态的 Handler 对象,为了能够将执行环境切换到主线 程,这就要求 sHandler 这个对象必须在主线程创建。由于静态成员会在 加载类的时候进行初始化,因此这就变相要求 AsyncTask 的类必须在主线 程中加载,否则同一个进程中的 AsyncTask 都将无法正常工作。

使用AsyncTask的规则

  1. AsyncTask 的类必须在 UI 线程加载(从 4.1 开始系统会帮我们自动完成)。AsyncTask 对象必须在 UI 线程创建。
  2. execute 方法必须在 UI 线程调用。
  3. 不要在你的程序中去直接调用 onPreExecute(), onPostExecute, doInBackground, onProgressUpdate 方法。
  4. 一个 AsyncTask 对象只能执行一次,即只能调用一次 execute 方法,否则会报运行时异常。
  5. AsyncTask 不是被设计为处理耗时操作的,耗时上限为几秒钟,如果要做长耗时操作,强烈建议你使用 Executor,ThreadPoolExecutor 以及 FutureTask。
  6. 在 1.6 之前,AsyncTask 是串行执行任务的,1.6 的时候 AsyncTask 开始采用线程池里处理并行任务,但是从 3.0 开始,为了避免 AsyncTask 所带来的并发错误,AsyncTask 又采用一个线程来串行执行任务。
  7. asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, Params... params),通过这个方法我们可以自定义 AsyncTask 的执行方式,串行 or 并行,甚至采用自己的Execuor。
  8. execute(Runnable runnable),这是 AsyncTask 提供的一个静态方法,方便我们直接执行一个 runnable。

AsyncTask里的线程池

AsyncTask 对应的线程池 ThreadPoolExecutor 都是进程范围内共享的,且都是static 的,所以是 Asynctask 控制着进程范围内所有的子类实例。由于这个限制的存在,当使用默认线程池时,如果线程数超过线程池的最大容量,线程池就会爆掉(3.0 后默认串行执行,不会出现个问题)。针对这种情况,可以尝试自定义线程池,配合 Asynctask 使用。

AsyncTask里面线程池是一个核心线程数为CPU + 1,最大线程数为CPU * 2 + 1, 工作队列长度为128的线程池,线程等待队列的最大等待数为 28,但是可以自定义线程池。线程池是由 AsyncTask 来处理的,线程池允许 tasks 并行运行,需要注意的是并发情况下数据的一致性问题,新数据可能会被老数据覆盖掉。所以希望 tasks 能够串行运行的话,使用 SERIAL_EXECUTOR。

AsyncTask生命周期问题

  1. 一个在 Activity 中创建的 AsyncTask 不会随着 Activity 的销毁而销毁。AsyncTask 会一直执行,直到 doInBackground()方法 执行完毕 。
  2. 如果 cancel(boolean)被调用,那么 onCancelled(Result result) 方法会被执行。否则,执行onPostExecute(Result result)方法 。
  3. 必须确保在销毁活动之前取消任务。 总之,我们使用 AsyncTask 需要确保 AsyncTask 正确的取消。

AsyncTask内存泄漏问题

如果 AsyncTask 被声明为 Activity 的非静态内部类,那么 AsyncTask 会保留一个 对 Activity 的引用。如果 Activity 已经被销毁,AsyncTask 的后台线程还在执行, 它将继续在内存里保留这个引用,导致 Activity 无法被回收,引起内存泄漏。

AsyncTask结果丢失问题

屏幕旋转或 Activity 在后台被系统杀掉等情况会导致 Activity 的重新创建,之前运行的 AsyncTask 会持有一个之前 Activity 的引用,这个引用已经无效,这时调用 onPostExecute()再去更新界面将不再生效。

AsyncTask并行还是串行

在 Android1.6 之前的版本,AsyncTask 是串行的,在 1.6 之后的版本,采用线程 池处理并行任务,但是从 Android 3.0 开始,为了避免 AsyncTask 所带来的并发 错误,又采用一个线程来串行执行任务。可以使用 executeOnExecutor()方法来并行地执行任务。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 什么是AsyncTask
  • AsyncTask原理
  • 使用AsyncTask的规则
  • AsyncTask里的线程池
  • AsyncTask生命周期问题
  • AsyncTask内存泄漏问题
  • AsyncTask结果丢失问题
  • AsyncTask并行还是串行
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档