Kotlin Coroutine withContext、async await - chuwuwang/ReadingNote GitHub Wiki
withContext
调用 withContext 函数之后,会立即执行代码块中的代码,同时将当前协程阻塞住。当代码块中的代码全部执行完之后,会将最好一行的执行结果作为 withContext 函数的返回值返回。因此基本上相当于 val result = async { }.await() 的写法。
唯一不同的是,withContext 函数强制要求我们指定一个线程参数。
async await
async 函数必须在协程作用域中才能调用,它会创建一个新的子协程并返回一个 Deferred 对象。如果我们想要获取 async 函数代码块的执行结果,只要调用 Deferred 对象的 await() 方法即可。
在调用了 async 函数之后,代码块中的代码就会立即开始执行。当调用 await 函数时,如果代码块中的代码还没有执行完,那么 await 函数就会阻塞当前协程,知道可以获得 async 函数的结果。
async 的函数签名和 launch 几乎完全相同,同样是 CoroutineScope 的一个扩展函数,用于开启一个新的子协程,与 launch 函数一样可以设置启动模式,不同的是它的返回值为 Deferred,Deferred是Job的子类,但是通过Deferred.await()可以得到一个返回值,简单理解的话,这就是一个带返回值的 launch 函数。
async/await 是 Future/Promise 模型的非阻塞版,所以可以像 Promise 一样方便地实现各种顺序的逻辑,且不必担心阻塞线程。launch 和 async的唯一区别在于async的返回值。async 返回的是 Deferred 类型,Deferred 继承自 Job 接口,Job有的它都有,增加了一个方法 await ,这个方法接收的是 async 闭包中返回的值,async 的特点是不会阻塞当前线程,但会阻塞所在协程,也就是挂起。但是需要注意的是 async 并不会阻塞线程,只是阻塞锁调用的协程。
async 和 launch 的区别
launch 更多是用来发起一个无需结果的耗时任务,这个工作不需要返回结果。
async 函数则是更进一步,用于异步执行耗时任务,并且需要返回值(如网络请求、数据库读写、文件读写),在执行完毕通过 await() 函数获取返回值。