Kotlin 协程
协程基于线程,是轻量级的线程。
协程可以让异步逻辑的代码同步化。
使用kotlin协程需要添加依赖库:
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.2'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.2'
第二个依赖是在Android项目中才会用到。
最简单方式创建协程:
GlobalScope.launch {
println("Hello World!")
delay(1000)
}
Thread.sleep(1000)
GlobalScope.launch创建的是顶层协程,这种协程会随着应用程序的结束而结束。
delay()函数是一个非阻塞式的挂起函数,它只会挂起当前协程,并不影响其它协程的运行。而Thread.sleep()方法会阻塞当前的线程。delay()函数只能在协程的作用域或其它挂起函数中调用。
runBlocking 函数会创建一个协程作用域,但它可以保证在协程作用域内的所有代码和协程没有执行完之前一直阻塞当前线程。
launch函数可以创建一个新的子协程。
runBlocking {
launch {
delay(1000)
println("launch1")
}
launch {
delay(1000)
println("launch1")
}
}
使用suspend关键字可将函数声明为挂起函数:
suspend fun printDot() = coroutineScope {
launch {
println(".")
delay(1000)
}
}
coroutineScope函数是一个挂起函数,可以在其它挂起函数中调用,它会继承外部的协程的作用域并创建一个子协程,这样就可以给任意挂起函数提供协程作用域了。
async函数与await函数
async函数创建一个新的子协程并返回一个Deferred对象,如果我们想要获取async函数代码块的执行结果,只需调用Deferred对象的await()方法即可:
runBlocking {
val result = async {
1 + 1
}.await()
println(result)
}
withContext()
withContext()也是一个作用域构建起,它是一个挂起函数。代码块的最后一行会作为该函数的返回值。
使用withContext()需要指定线程参数:Dispatchers.IO、Dispatchers.Ddefault、Dispatchers.Main。
runBlocking {
val result = withContext(Dispatchers.Default) {
1 + 1
}
println(result)
}
使用协程简化回调的写法
suspend fun request(address: String): String {
return suspendCoroutine { continuation ->
HttpUtil.sendHttpRequest(address, object : HttpCallbackListener {
override fun onFinish(response: String) {
continuation.resume(response)
}
override fun onError(e: Exception) {
continuation.resumeWithException(e)
}
})
}
}
suspend fun getBaiduResponse() {
try {
val response = request("https://www.baidu.com/")
// 处理数据
}catch (e: Exception){
// 处理异常
}
}
使用协程简化Retrofit发起网络请求
suspend fun <T> Call<T>.await(): T {
return suspendCoroutine { continuation ->
enqueue(object : Callback<T>) {
override fun onResponse(call: Call<T>,response: Response<T>) {
val body = response.body()
if (body != null ) continuation.resume(body)
else continuation.resumeWithException(
kotlin.RuntimeException("response body is null")
)
}
override fun onFailure(call: Call<T>,t: Throwable) {
continuation.resumeWithException(t)
}
}
}
}
suspend fun getUserData() {
try {
val userList = ServiceCreator.create<AppService>().getUserData().await()
// 处理响应数据
}catch (e: Exception){
// 处理异常
}
}