AsyncTask被废弃了,换Coroutine吧
本文主要是学习笔记,有版权问题还请告知删文
鸣谢:guolin@第一行代码(第三版)
你是否也在最近的代码中看见了 AsyncTask 被一条横杠划掉了
这表明——他要被Google放弃了

Google说让我们换成协程,也就是Coroutine,我们来看看怎么无缝切换
1. 添加依赖
首先,他并不是在标准库里,所以我们要添加依赖
dependencies {
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.7"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.7"
}
2. 使用协程
2.1 GlobalScope.launch
最简单的方法就是调用GlobalScope.launch
这里每创建一个协程都是顶层协程!对!没错!协程是分层级
GlobalScope.launch {
//do something
}
这个函数的特点就是:自己闷头执行,主线程结束,他也结束(虽然有可能没执行完)
2.2 runBlocking
runBlocking从字面意思就可以理解,运行并阻塞,意思是运行协程,并在携程未结束时阻塞当前线程
runBlocking{
//do something
}
这个函数的特点就是:执行时阻塞当前线程
此方法一般用在测试环境,实际使用中容易有性能问题
2.3 多协程
多协程只要我们这么写就可以
runBlocking{
launch{
//do something#1
}
launch{
//do something#2
}
launch{
//do something#3
}
}
这样我们就创建了3个子协程
注意,我们这里的launch和GlobalScope.launch有一些区别,GlobalScope创建的是顶层协程
另外,我们的多协程还是运行在一个线程里面的,也就是3个协程运行在一个线程里面
到这里,相信你们都有了一种奇怪的感觉,一个线程里实现并发???
我要说的是:没错!
因此它不需要操作系统的参与,像是子协程有一百万个,它也不会产生OOM
我测试了1000000个协程总共消耗了5722ms,也就是5秒
高并发效率非常高
2.4 suspend关键字(能在协程里调用的函数)
别担心,这跟Java废弃的那个强制挂起线程的函数没什么关系,只是恰巧长得一样而已@Java suspend()
当你的代码过多导致可读性很差的时候,就需要将部分代码写成一个函数,这时候就需要用到suspend,这样我们就可以在协程作用域里面调用该函数
用guolin大神的话说,就是“suspend可以将我们的函数声明成挂起函数”
我理解的是,挂起函数可以在其内部调用其他的挂起函数,比如:delay()
suspend fun 函数名(参数列表){
//do something
}
但是suspend并不会让我们的函数就像在协程作用域里写的一样,比如:无法调用launch创建子协程
这时我们就需要调用corountineScope函数
suspend fun 函数名(参数列表) = corountineScope{
launch{
//do something
}
}
corountineScope 是会在其作用域里的程序执行完成前阻塞当前协程的,但它不会影响其他协程,也不会影响线程
而且它只能在 协程作用域 或 挂起函数 下调用
runBlocking {
launch {
println("即将被阻塞")
coroutineScope{
for (i in 1..3){
println("阻塞中")
delay(10)
}
}
println("阻塞结束")
}
launch {
println("我没被阻塞")
}
}
这个运行结果就会是这样的
即将被阻塞
阻塞中
我没被阻塞
阻塞中
阻塞中
阻塞结束
3. 取消协程(关掉它!!!)
launch函数会返回一个Job类型的对象
Job类里面有一个cancel函数,调用它就可以取消协程
val job = Job()
val scope = CoroutineScope(job)
scope.launch{
//do something
}
job.cancel()
这就是一般情况下项目里协程的写法
这里还有一个要注意的,第二行的CoroutineScope(job)并不是CoroutineScope的构造函数,而是一个单独的函数
至于为啥Kotlin要把这个函数名首字母大写,我也不知道...
4. 获得协程运行结果
4.1 async
假设我们在需要进行一个耗时操作,我们将这个任务放到协程里,可我们不知道什么时候能获得这个结果,而launch最终也只是返回一个Job对象,这样的机制不利于我们处理结果,所以为了获得我们需要的结果,async函数就必不可少了,async会新建一个子协程并返回一个Deferred对象,Deferred里有一个await函数,他就会给我们想要的结果
还有一点相信你已经想到了,await会阻塞当前的协程,直到获得我们想要的结果
写法如下
runBlocking {
val result = async {
//do something
}.await()
}
其中常量result就是我们需要的结果
这里需要注意的是,如果你有多个结果需要获取,一定要明白其中的逻辑关系然后优化好代码
比如:我们需要用A和B生成E,C、D生成F,E、F生成result

代码就应该这么写
val job = Job()
val scope = CoroutineScope(job)
scope.launch {
val E = async {
//A和B生成E
}
val F = async {
//C和D生成F
}
val result = async {
//E.await() 和 F.await() 生成
}
}
4.2 withContext
写法如下
runBlocking {
val result = withContext(Dispatchers.Default) {
//do something
}
}
还是引用guolin大神的话:withContext可以理解为async的简化版写法。
调用 withContext 会立刻执行代码块里的代码,同时将当前的协程阻塞。代码块执行完后,会将最后一行的结果当做返回值返回。唯一不同的是他有个参数。
简而言之,就是没有 await 函数,没法灵活控制协程阻塞,除此之外多了个参数,其他和async区别不大
guolin大神还说了:withContext是强制要求输入参数的。而刚才提到的除了coroutineScope,其他所有的协程作用域构建器也都可以指定参数,只不过不强制
那么这个参数是干嘛的呢???
答案是用来选择并发线程策略的,这种参数主要有三种可选:Dispatchers.Default、Dispatchers.IO、Dispatchers.Main
是的,你没听错,线程策略,是线程,也就是说,他会创建线程来帮助实现并发,要知道网络请求是只能在线程里实现并发的,协程是不行的。
| Dispatchers.Default | 默认的低并发线程策略 |
|---|---|
| Dispatchers.IO | 高并发线程策略 |
| Dispatchers.Main | 不开启线程 |
5. 回调简写(suspendCoroutine)
我们回调的通常写法是:
HttpUtil.sendHttpRequest(address : String , object : HttpCallbackListener {
override fun onFinish() {
//do something
}
override fun onError() {
//do something
}
})
类似这样,代码就很多,动个手指头都嫌累
Kotlin就给了我们一个解决策略
用suspendCoroutine函数!
suspendCoroutine必须在协程域中或挂起函数里调用
它接受一个lambda表达式参数,主要作用是将当前协程立刻挂起,然后在一个普通线程(guolin大神的话,我理解的是非主线程就行)里执行lambda表达式中的代码。
lambda表达式又传入一个Continuation参数,调用它的resume() 或 resumeWithException() 就可以让协程恢复执行。
代码示例:
suspend fun request(address: String): String {
return suspendCoroutine { contination ->
HttpUtil.sendHttpRequest(address, object : HttpCallbackListener {
override fun onFinish(Response: String) {
contination.resume(Response)
}
override fun onError(e: Exception) {
contination.resumeWithException(e)
}
})
}
}
然后你就想骂我,这TM不是更多了吗???
你调用试试...
suspend fun getBaiduResult(){
try{
val result = request ( "https://www.baidu.com" )
//对result进行处理
}catch{
//异常处理
}
}
爽不爽!?
还没写完,忙的抽不出时间写了 T^T
AsyncTask被废弃了,换Coroutine吧的更多相关文章
- Mastering MariaDB 神秘的MariaDB 中文翻译版
是某群的哥们义务翻译的,宣传一下,还没时间时间读,粗滤看了全部翻译完了300多页佩服 https://github.com/CMant/Mastering-MariaDB- 原地址:如果你需要读,请s ...
- updataxml报错注入
// take the variables//接受变量 // //也就是插入post提交的uname和passwd,参见:https://www.w3school.com.cn/sql/sql_ins ...
- svn更新路径,解决办法详细步骤,eclipse里面的更新方法,svn废弃位置,Windows环境,svn服务器地址换了,如何更新本地工作目录
svn更新路径,解决办法详细步骤,eclipse里面的更新方法,svn废弃位置,Windows环境,svn服务器地址换了,如何更新本地工作目录 Windows下,svn服务器IP本来是内网一台服务器上 ...
- Kotlin Coroutine(协程): 二、初识协程
@ 目录 前言 一.初识协程 1.runBlocking: 阻塞协程 2.launch: 创建协程 3.Job 4.coroutineScope 5.协程取消 6.协程超时 7.async 并行任务 ...
- Coroutine in Java - Quasar Fiber实现--转载
转自 https://segmentfault.com/a/1190000006079389?from=groupmessage&isappinstalled=0 简介 说到协程(Corout ...
- mysql_connect() php7不支持,php5.5可以,是废弃函数
天用了PHP7,发现和PHP5变化还挺大的,最大的就是MySQL的连接库变了. PHP5中使用mysql_connect()函数进行连接,但实际上,PHP5.5开始,MySQL就不推荐使用了,属于废弃 ...
- Android中AsyncTask分析--你所不注意的坑
AsyncTask,是android提供的轻量级的异步类,可以直接继承AsyncTask,在类中实现异步操作,并提供接口反馈当前异步执行的程度(可以通过接口实现UI进度更新),最后反馈执行的结果给UI ...
- Unity协程(Coroutine)原理深入剖析
Unity协程(Coroutine)原理深入剖析 By D.S.Qiu 尊重他人的劳动,支持原创,转载请注明出处:http.dsqiu.iteye.com 其实协程并没有那么复杂,网上很多地方都说是多 ...
- C#中的yield return与Unity中的Coroutine(协程)(下)
Unity中的Coroutine(协程) 估计熟悉Unity的人看过或者用过StartCoroutine() 假设我们在场景中有一个UGUI组件, Image: 将以下代码绑定到Image using ...
随机推荐
- java 面向对象(二十九):异常(二)异常的处理
1.java异常处理的抓抛模型过程一:"抛":程序在正常执行的过程中,一旦出现异常,就会在异常代码处生成一个对应异常类的对象. * 并将此对象抛出. * 一旦抛出对象以后,其后的代 ...
- ASP.NET Core策略授权和 ABP 授权
目录 ASP.NET Core 中的策略授权 策略 定义一个 Controller 设定权限 定义策略 存储用户信息 标记访问权限 认证:Token 凭据 颁发登录凭据 自定义授权 IAuthoriz ...
- Kafka Eagle V2.0.0新版预览
1.概述 Kafka Eagle是一款用于管理Kafka的监控系统,且完全开源.当前Kafka Eagle发布了2.0.0版本.今天笔者就为大家来介绍一下2.0.0更新了哪些功能. 官网地址:http ...
- Python数据分析实战:使用pyecharts进行数据可视化
前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者:刘早起 开始使用 基本套路就是先创建一个你需要的空图层,然后使用.s ...
- Python Ethical Hacking - NETWORK_SCANNER(2)
DICTIONARIES Similar to lists but use key instead of an index. LISTS List of values/elements, all ca ...
- 彻底禁用咱的Win10电脑更新
一.关闭Windows Update服务 右键“此电脑”>“管理” 找到Windows Update服务双击打开,服务状态>停止,服务类型>禁用 “恢复”选项卡,三项全部选择“无操作 ...
- windows docker xshell 默认登录密码
boot2docker用户和密码 用户 密码 进入方式 docker tcuser ssh root command:sudo -i (docker用户下执行)
- vue的双向数据绑定实现原理(简单)
如果有人问你,学vue学到了什么,那双向数据绑定,是必然要说的. 我们都知道,在vue中,使用数据双向绑定我们都知道是v-modle实现的. 实现原理是通过Object.defineProperty的 ...
- Postman安装失败
https://blog.csdn.net/qq_21282443/article/details/86213972
- 【新生学习】第一周:深度学习及pytorch基础
DEADLINE: 2020-07-25 22:00 写在最前面: 本课程的主要思路还是要求大家大量练习 pytorch 代码,在写代码的过程中掌握深度学习的各类算法,希望大家能够坚持练习,相信经度过 ...