1.协程的创建方式
1.使用 launch()
实例如下:
GlobalScope.launch {
delay(3000)
}
launch()函数的源代码如下:
public fun CoroutineScope.launch(
context: CoroutineContext = EmptyCoroutineContext,
start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> Unit
): Job {
val newContext = newCoroutineContext(context)
val coroutine = if (start.isLazy)
LazyStandaloneCoroutine(newContext, block) else
StandaloneCoroutine(newContext, active = true)
coroutine.start(start, coroutine, block)
return coroutine
}
context :
接收一个可选的 CoroutineContext 参数,是一些元素的集合,主要包括 Job 和 CoroutineDispatcher 元素。可以代表一个协程的场景。默认值EmptyCoroutineContext,表示运行在父协程的上下文中。 其他值如下
Dispatchers.Unconfined :协程调度器会在程序运行到第一个挂起点时,在调用者线程中启动。挂起后,它将在挂起函数执行的线程中恢复,恢复的线程完全取决于该挂起函数在哪个线程执行。非受限调度器适合协程不消耗 CPU 时间也不更新任何限于特定线程的共享数据(如 UI)的情境。
Dispatchers.Default : 将会获取默认调度器,使用共享的后台线程池
newSingleThreadContext(“MyOwnThread”) :将使它获得一个新的线程, 在真实的应用程序中两者都必须被释放,当不再需要的时候,使用 close 函数,或存储在一个顶级变量中使它在整个应用程序中被重用。
Dispatchers.IO : 运行在IO线程中
Dispatchers.Main : 运行在主线程中
newFixedThreadPoolContext(2,“ss”):运行在一个新的线程池里面,当不再需要的时候,使用 close 函数,或存储在一个顶级变量中使它在整个应用程序中被重用。
协程的 Job 是它上下文中的一部分。协程可以在它所属的上下文中使用 coroutineContext[Job] 表达式来取回它:
println("My job is ${coroutineContext[Job]}")
判断协程的状态
start :
协程启动的设置,一般使用默认值,还未遇到使用其他值的情况
block :
需要再协程中执行的代码
返回值是一个Job对象
2.使用 async()
实例如下:
GlobalScope.async {
delay(3000)
}
aysnc()函数与launch()函数相同,唯一的区别是它有返回值,因为async {}返回的是 Deferred 类型。获取async {}的返回值需要通过await()函数,它也是是个挂起函数,调用时会挂起当前协程直到 async 中代码执行完并返回某个值。
3.使用 withContext{}
实例如下:
GlobalScope.async (Dispatchers.Main) {
withContext(coroutineContext){
delay4s()
}
}
withContext {}不会创建新的协程,在指定协程上运行挂起代码块,并挂起该协程直至代码块运行完成。
4.使用 runBlocking {}
实例如下:
fun main() = runBlocking {
delay(1000)
}
runBlocking {}是创建一个新的协程同时阻塞当前线程,直到协程结束。这个不应该在协程中使用,主要是为main函数和测试设计的。
在Android中一般会使用GlobalScope.async()函数和GlobalScope.launch()函数启动协程,他们分别对应async()和launch()函数只是他们的协程的生命周期只受整个应用程序的生命周期限制。然后再这两个函数之中可以使用上述那些函数创建子协程。而且GlobalScope.launch{}和GlobalScope.async{}新建的协程是没有父协程的。
2. Job & Deferred
Job,任务,封装了协程中需要执行的代码逻辑。Job 可以取消并且有简单生命周期,它有三种状态:
Job 完成时是没有返回值的,如果需要返回值的话,应该使用 Deferred,它是 Job 的子类,返回值可以通过await()函数获取