协程的定义其实不太好描述,那我干脆由用途及定义,简述一下协程。
标题的说法可能不太准确,但也能一窥其功用。协程是工作在线程之上的。我们知道线程是由系统(语言系统或者操作系统)进行调度的,切换时有着一定的开销。而协程,它的切换由程序自己来控制,无论是 CPU 的消耗还是内存的消耗都大大降低。
从这一点出发,它的应用场景可能就在于提高硬件性能的瓶颈。譬如说,你启动十万个协程不会有什么问题,但你启动十万个线程试试?
相较于第一点,这才是协程的本质;同时也是由这一点,协程发挥了很大的作用。在协程中,某段代码可以暂停,转而去执行另外的协程代码;被暂停的代码也可以在你的控制下随时恢复运行。
这在前端编程中有一个很大的用处——避免回调地狱。就 Android 编程而言,在 Rx 之前,要获取某个异步操作的返回结果,标准做法就是定义接口,用回调来接收结果。而 Rx 出现之后,以其巧妙的转换,通过响应式的代码,以一层的回调(辅以 lambda 表达式,看起来就像没有回调一样)链解决了回调地狱的问题。但在这里,习惯以命令式写法写代码的同学就需要稍稍理解一些函数式的编程思维了。协程不一样,它的代码是可以暂停的!也就是说,在我通过 getUser()
方法异步获取数据的时候,调用它的代码块就可以选择挂起,等到获取到数据,再恢复运行。代码看起来就这样:
val user = getUser() // 这儿的 getUser 就是 suspend function
是不是和同步代码看起来一样?
写过 JS 的同学可能就觉着很眼熟了:
async function getUser() {
try {
const response = await fetchUser();
// …
} catch (e) {
// error handle
}
}
没错,通过协程,Kotlin 是可以写出类似代码来的!
首先,需要通过构造器来启动协程。官方目前提供的基础构造器有两个:
launch
runBlocking
它们都会启动一个协程,区别在于前者不会阻塞当前线程,并且会返回一个协程的引用,而后者会等待协程的代码执行结束,再执行剩下的代码。
其次,关于协程,Kotlin 新增了一个关键字:suspend
,被该关键字修饰的函数/方法/代码块只能由协程代码(也就是上述构造器的代码块参数内部)或者被 suspend
修饰的函数/方法/代码块调用。说简单一点,suspend fun
只能被 suspend fun
调用(协程构造器的最后一个参数的类型声明就是 suspend CoroutineScope.() -> Unit
)。
知道了这两点,就可以写出最简单的协程代码:
fun main(args: Array) {
repeat(100_000) { // 启动十万个协程试试
launch { suspendPrint() }
}
Thread.sleep(1200) // 等待协程代码的结束
}
suspend fun suspendPrint() {
delay(1000)
println(“.”)
}
其中的 delay
就是一个 suspend fun
。
除了以上两点,另一个很重要的概念就是上下文(context
)。协程虽然是依赖于线程的,但一个协程并非就绑死在一个线程上。启动协程的时候可以指定上下文,在协程内部也可以通过 withContext
切换上下文。而这个上下文,也就是一个 CoroutineDispatcher
类的对象,从名字可以看出,就是由它去进行协程调度。比如,如果你需要新建一个线程去跑协程的代码,可以这样:
launch(context = newSingleThreadContext(“new-thread”)) { delay(1000) }
以上三点是我个人认为重要的内容,当然还有协程的取消、协程的生命周期、协程与子协程的关系等等,这些要点可以去官方文档或者我的翻译查看,内容写得很棒。
就我个人所知,async
与 await
作为 JS 与 C# 的两个关键字,精简了异步操作(当然,这两门语言的细节并不一样)。但是在 Kotlin 中,async 其实是一个普通的函数:
fun main(args: Array) = runBlocking {
val result: Deferred = async { doSomethingTimeout() }
println(“I will got the result ${result.await()}”)
}
suspend fun doSomethingTimeout(): String {
delay(1000)
return “Result”
}
在这里, async
代码块会新启动一个协程后立即执行,并且返回一个 Deferred
类型的值,调用它的 await
方法后会暂停当前协程,直到获取到 async
代码块执行结果,当前协程才会继续执行。
其实谈到这个,就不得不提一下 Retrofit 了,作为 RESTful 架构的优秀解决方案,有人已经为其适配了协程版的 adapter 了。我知道的有两个:
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
针对Android程序员,我这边给大家整理了一些资料,包括不限于高级UI、性能优化、架构师课程、NDK、混合式开发(ReactNative+Weex)微信小程序、Flutter等全方面的Android进阶实践技术;希望能帮助到大家,也节省大家在网上搜索资料的时间来学习,也可以分享动态给身边好友一起学习!
Android高级架构资料、源码、笔记、视频。高级UI、性能优化、架构师课程、混合式开发(ReactNative+Weex)全方面的Android进阶实践技术,群内还有技术大牛一起讨论交流解决问题。
一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**
[外链图片转存中…(img-YwDhKKcu-1712797587070)]