而对于kotlin中协程最重要的一点特点是,是可以用同步的方式写出异步的代码
coroutineScope.launch(Dispatchers.Main) { // 开始协程:主线程val token = api.getToken() // 网络请求:IO 线程val user = api.getUser(token) // 网络请求:IO 线程nameTv.text = user.name // 更新 UI:主线程}
启动一个协程可以使用 launch 或者 async 函数,协程其实就是这两个函数中闭包的代码块
当线程执行到协程的 suspend 函数的时候,暂时不继续执行协程代码了。
run code ..
// 主线程中
GlobalScope.launch(Dispatchers.Main) {
val image = suspendingGetImage(imageId) // 获取图片
avatarIv.setImageBitmap(image) // 显示出来
}
suspend fun suspendingGetImage(id: String) = withContext(Dispatchers.IO) {
...
}
当线程执行到“suspend 函数”时,它实质上会往你的主线程 post 一个 Runnable,这个 Runnable 就是你的协程代码:
handler.post {
val image = suspendingGetImage(imageId)
avatarIv.setImageBitmap(image)
}
然后线程就被掐断了,
我们的协程,它从 suspend 函数开始脱离启动它的线程,继续执行在 Dispatchers 所指定的 IO 线程。
紧接着在 suspend 函数执行完成之后,协程为我们做的最爽的事就来了:会自动帮我们把线程再切回来。
而切回来这个功能是协程的,如果你不在协程里面调用,恢复这个功能没法实现,所以也就回答了这个问题:为什么挂起函数必须在协程或者另一个挂起函数里被调用。
- 协程是什么
协程就是切线程;
- 挂起是什么
挂起就是可以自动切回来的切线程;
- 挂起的非阻塞式
挂起的非阻塞式指的是它能用看起来阻塞的代码写出非阻塞的操作。
suspend
suspend中文意思是「暂停」或者「可挂起」
在之前我们讲到的协程的挂起,而挂起就是通过suspend来实现的
对于自定义挂起函数,需要在该函数内部直接/间接调用到某一个自带的挂起函数才行
【例如withContext()】
suspend fun getImage(imageId: Int) = withContext(Dispatchers.IO) {
...
}
suspend关键字到底什么作用
作用是:[提醒]
函数的创建者对函数的调用者的提醒
“我”是一个耗时的函数,我被我的创建者用挂起的方式放到了后台运行,所以要在协程里调用“我”。
