【源码】康一康过时的→AsyncTask(上)

简介: AsyncTask 对很多老Android来说,是一个很有年代感的东西了,想当年毕业找工作,AsyncTask可是面试必问。随着 EventBus、RxJava、Kotlin协程 等的出现,它渐渐淡出了我们的视野,面试八股文也少了它的身影,很多新晋的Android开发估计都没听过它。不禁感叹:技术更新迭代真快,学不动了!面试不问,但一些老旧项目中还有用到它,接盘维护难免要学下,索性花一丢丢时间过一下:废弃原因 + 核心原理 + 演进历史。

0x1、Deprecated 原因


AsyncTask,Android(API 3) 引入,一个轻量级的异步任务库,允许以 非线程堵塞 的方式执行操作。经过了好几个版本的调整,比如:


  • Android 1.6前,串行执行,原理:一个子线程进行任务的串行执行;


  • Android 1.6到2.3,并行执行,原理:一个线程数为5的线程池并行执行,但如果前五个任务执行时间过长,会堵塞后续任务执行,故不适合大量任务并发执行;


  • Android 3.0后,串行执行,原理:全局线程池进行串行处理任务;


还有一些小调整,比如Android 10后,线程池核心数变成1,线程队列从BlockingQueue变成SynchronousQueue等。


真够折腾的,打开 AsyncTask的官方文档 一行橙字映入眼帘:


网络异常,图片无法展示
|


AsyncTask类在 Android 11(API 30) 中被废弃了,推荐使用java.util.concurrent或Kotlin协程来替代。


em...就废弃了啊,往下看是废弃原因的解释:


网络异常,图片无法展示
|


大概意思:


  • AsyncTask本意是使得UI线程的使用变得简单正确,但最常见的用法是集成到UI中,反而导致了 Context泄露、忘记回调、configuration变化Crash 问题。


  • 不同版本AsyncTask的兼容问题;


  • 吞掉了来自doInBackground的异常;


  • 不能提供比直接使用Executor更多的功能;


  • Thread和Handler的辅助类,并非线程框架,主要用于执行一些时间不太长的异步任务;


  • 用法复杂,三个通用参数(Params、Progress、Result) + 四个回调方法;


简单概括下:版本兼容功能少用起来还麻烦


0x2、AsyncTask 用法详解


Talk is cheap,show you the Code,了解完过时原因,接着温习下它的用法:


// 继承AsyncTask抽象类,建议声明为Activity的静态内部类,避免context泄露
    // 泛型参数依次为:
    // 
    // Params → 开始异步任务时传入的参数类型 → execute(Params)
    // Progress → 异步任务执行过程,返回进度值
    // Result → 异步任务执行完成后,返回结果类型 → doInBackground()
    // 
    class MyAsyncTask: AsyncTask<Task, Int, String>() {
        // 必须重写!在此执行耗时操作,返回执行结果
        override fun doInBackground(vararg params: Task?): String { return "执行耗时操作" }
        // 执行线程任务前的回调,即执行execute()前自动调用,常用作界面初始化操作
        override fun onPreExecute() { }
        // 在主线程中显示任务执行的进度,自动调用啊,按需重写
        override fun onProgressUpdate(vararg values: Int?) { }
        // 接受线程任务执行结果,线程任务结束时自动调用,可在此将结果更新到UI组件
        override fun onPostExecute(result: String?) { }
        // 异步任务被取消时自动调用,用于将异步任务设为取消状态,需在doInBackground()中停止
        // 此方法调用onPostExecute就不会被调用
        override fun onCancelled() {}
    }
    // 在主线程中初始化自定义AsyncTask实例后,调用execute(XXX)
    // 每个AsyncTask实例只能调用一次execute(),多次调用会抛出异常
    // 注①:Activity重建(如屏幕旋转),之前持有的Activity引用已失效,任务正常运行,
    // 但任务执行完成后,在onPostExecute中修改UI不会生效,建议在Activity恢复的相关方法
    // 中重启AsyncTask任务;
    // 注②:最好在Activity、Fragment的onDestory()中调用AsyncTask.cancle()将AsyncTask设置
    // 为canceled状态,然后在doInBackground中去判断这个AsyncTask的status是否为:
    // AsyncTask.Status.RUNNING,是,直接返回,结束任务
}


em...用法看着也不算太复杂 (不和rx、协程等对比的话),接着以Android 9.0源码为例,讲解一波核心原理~


0x3、核心原理讲解


① 单个任务的流转


execute()executeOnExecutor()


网络异常,图片无法展示
|


AsyncTask内部定义了一个状态字段 mStatus,可选值有:PENDING(挂起)RUNNING(运行中)FINISHED(结束)


从上述代码也可以看出为何**不能重复调用AsyncTask实例的execute()**方法,接着看下工作线程 →  mWorker


网络异常,图片无法展示
|


看完定义,看实现:


网络异常,图片无法展示
|


目录
打赏
0
0
0
0
7
分享
相关文章
Android面试中问的线程相关问题
Android面试中问的线程相关问题
139 0
【视频直播篇一】入门篇
公司产品要集成视频直播,原来找的一家第三方厂家已经对接好了,后来领导说成本太高要换。拿到同行的产品来看,发现他们用的是rtmp协议的直播流。领导说要上这个,把这个任务交给我,当时都蒙圈了。这啥玩意?!从来没见过啊。领导的话就是命令,没办法,硬着头皮也要上。 花了几天时间稍微入了门,在这里总结一下。 首先直播中有两个非常重要的概念:推流、拉流。通俗来讲,推流指的就是我们在直播平台看到的主播那一端采集摄像头数据推送到视频流服务器。而拉流就是观众这一段使用pc、移动端播放直播视频了。
664 0
Android获取设备各项信息(设备id、ip地址、设备名称、运行商、品牌、型号、分辨率、处理器、国家码、系统语言、网络类型、oaid、android版本、操作系统版本、mac地址、应用程序签名..)2
Android获取设备各项信息(设备id、ip地址、设备名称、运行商、品牌、型号、分辨率、处理器、国家码、系统语言、网络类型、oaid、android版本、操作系统版本、mac地址、应用程序签名..)2
641 2
|
12月前
|
jni编程(windows+JDK11+clion)
jni编程(windows+JDK11+clion)
164 1
|
12月前
|
【技术觉醒】JAVA高手必备:URL与URLConnection,解锁网络资源的终极秘籍!
【6月更文挑战第21天】Java网络编程中,URL和URLConnection是关键。案例一展示了如何使用它们从网站抓取数据:创建URL对象,打开连接,读取输入流获取HTML内容。案例二解释了POST请求:设定请求方法为POST,写入数据到输出流,上传至服务器。这两个基础工具在需要精细控制网络请求时尤其有用,是每个JAVA开发者必备技能。了解并熟练运用,能增强网络编程能力。
118 0
Android12 内置应用问题 mismatch in the <uses-library> tags between the build system and the manifest
Android12 内置应用问题 mismatch in the <uses-library> tags between the build system and the manifest
584 0
阿里云轻量应用服务器价格多少钱,2024年阿里云轻量应用服务器价格表整理
阿里云轻量应用服务器的价格根据配置和促销活动的不同而有所变化。在2024年,阿里云轻量应用服务器的价格范围较广,从61元一年起,到165元一年不等。具体的价格取决于服务器的配置,如CPU核数、内存大小、带宽等。 例如,阿里云轻量应用服务器的2核2G3M配置的价格为61元一年,而2核4G4M带宽的价格为165元一年。此外,阿里云还提供了其他配置选择,如4核8G8M带宽、8核16G10M带宽等,价格分别为322元一年和483元一年。
401 0
使用阿里云身份证扫描识别接口案例—
使用阿里云身份证扫描识别接口案例—