一、前言:
我们在开发过程中,很可能会遇到这样的需求,一个页面中需要同时请求好几个接口。
作用域学习:https://www.jianshu.com/p/70f8373932b8
二、Kotlin协程处理并发
1、先模拟2个请求
suspend fun one(): Int {
delay(1500)
return 1
}
suspend fun two(): Int {
delay(1500)
return 2
}
两个方法都是可挂起的方法,分别返回1和2
2、接口并发执行
假如这两个接口之间没有联系,我们想让他们并发执行的话,我们可以使用async和await配合使用。
代码如下:
fun main() {
GlobalScope.launch {
/*measureTimeMillis返回给定的block代码的执行时间*/
val time = measureTimeMillis {
val sum = withContext(Dispatchers.IO) {
val one = async { one() }
val two = async { two() }
one.await() + two.await()
}
println("两个方法返回值的和:${sum}")
}
println("执行耗时:${time}")
}
println("----------------")
/*应为上面的协程代码并不会阻塞掉线程,所以我们这里让线程睡4秒,保证线程的存活,在实际的Android开发中无需这么做*/
Thread.sleep(4000)
}
下面我们来运行看看执行结果:
总结:在协程作用域中请求使用async是同步执行,await并发返回结果。
3、Kotlin协程处理多个耗时操作按顺序执行
假如你有这样的需求,接口B的参数是接口A返回的结果,那这样的话,使用协程依然能够很简洁的实现。
我们把两个网络请求方法稍微改动一下:
suspend fun one(): Int {
delay(1000)
return 1
}
suspend fun two(int: Int): Int {
delay(2000)
return 2 + int
}
方法two接收一个参数,该参数是由方法one返回的结果决定的
实现代码如下:
fun main() {
GlobalScope.launch {
/*measureTimeMillis返回给定的block代码的执行时间*/
val time = measureTimeMillis {
val sum = withContext(Dispatchers.IO) {
val one = one()
val two = two(one)
one + two
}
println("两个方法返回值的和:${sum}")
}
println("执行耗时:${time}")
}
println("----------------")
/*应为上面的协程代码并不会阻塞掉线程,所以我们这里让线程睡4秒,保证线程的存活,在实际的Android开发中无需这么做*/
Thread.sleep(4000)
}
可以看到我们得到了想要的结果。
总结:在协程作用域中接口的执行顺序是串行的,one()执行完,再执行two()。
三、人工智能ChatGPT
1、Kotlin 协程请求,比如有1、2、3个请求,数据怎么一起返回?
在 Kotlin 中使用协程进行多个请求的并发处理可以使用 async 和 await 函数。以下是一个示例代码:
import kotlinx.coroutines.*
suspend fun requestData(url: String): String {
// 发送网络请求并返回数据
}
suspend fun main() {
val result = coroutineScope {
val request1 = async { requestData("http://example.com/api/1") }
val request2 = async { requestData("http://example.com/api/2") }
val request3 = async { requestData("http://example.com/api/3") }
"${request1.await()} ${request2.await()} ${request3.await()}"
}
println(result)
}
在上面的代码中,async 函数用于并发发送请求,而 await 函数则用于等待请求的结果返回。在 coroutineScope 内部使用 async 函数创建了三个协程,它们分别发送了三个请求。通过 await 函数等待这三个请求的结果返回后,将它们拼接在一起并返回。
在这个例子中,我们使用了 coroutineScope 函数来创建一个协程作用域,这样就可以在一个作用域中创建多个协程,并且等待它们全部完成后再返回结果。
2、Kotlin 协程请求,比如有1、2、3个请求,3要用2的返回值,2要用1的返回值,怎么请求?
在 Kotlin 中使用协程进行多个请求的并发处理,可以使用 async 和 await 函数。针对需要后续请求使用前面请求返回值的情况,可以使用 async 函数的 start 参数来控制协程的启动时间。以下是一个示例代码:
import kotlinx.coroutines.*
suspend fun requestData1(): Int {
// 发送网络请求并返回数据
}
suspend fun requestData2(value: Int): String {
// 发送网络请求并返回数据,使用前面请求的返回值
}
suspend fun requestData3(value: String): Boolean {
// 发送网络请求并返回数据,使用前面请求的返回值
}
suspend fun main() {
val result = coroutineScope {
val request1 = async { requestData1() }
val request2 = async(start = CoroutineStart.LAZY) { requestData2(request1.await()) }
val request3 = async(start = CoroutineStart.LAZY) { requestData3(request2.await()) }
"${request1.await()} ${request2.await()} ${request3.await()}"
}
println(result)
}
在上面的代码中,我们使用了 async 函数创建了三个协程。其中,第一个协程 request1 发送了第一个请求,并返回了一个 Int 类型的数据;第二个协程 request2 开启了延迟启动模式(start = CoroutineStart.LAZY),它会等待 request1 协程的结果返回后,再发送第二个请求,并返回一个 String 类型的数据;第三个协程 request3 同样开启了延迟启动模式,它会等待 request2 协程的结果返回后,再发送第三个请求,并返回一个 Boolean 类型的数据。
在 coroutineScope 内部,我们通过 await 函数等待三个请求的结果返回,将它们拼接在一起并返回。
需要注意的是,使用延迟启动模式的协程需要手动调用 await 函数来启动,否则它们不会执行。在上面的代码中,我们在 request2 和 request3 协程中使用了 await 函数来手动启动它们。
四、Kotlin协程项目实战(MVVM框架中进行)
1、创建请求作用域
//作用域
val mainScope = CoroutineScope(Dispatchers.Main + SupervisorJob())
2、同步并发请求(例如:A接口和B接口,返回结果组装)
//同步并发请求
mainScope.launch{
val request1 = async {
Log.d("lyy", "执行request1----开始:" + DateTimeHelper.format(Date(), "yyyy-MM-dd HH:mm:ss.SSS"))
apiService.getDiscoverData(map)
}
val request2 = async {
Log.d("lyy", "执行request2----开始:" + DateTimeHelper.format(Date(), "yyyy-MM-dd HH:mm:ss.SSS"))
apiService.getDiscoverData(map)
}
val await1= request1.await()
val await2= request2.await()
//需要手动处理异常情况
mainDiscoverData.value = await1.data
responseDiscoverFailData.value = false
MyToash.Log("lyy","----request1:${await1.data.label?.get(0)?.recommend_id}")
MyToash.Log("lyy","----request2:${await2.data.label?.get(0)?.recommend_id}")
}
请求接口时间:
//请求接口时间
执行request1----开始:2023-03-15 11:52:00.054
执行request2----开始:2023-03-15 11:52:00.063
3、默认串行请求接口(例如:B接口需要A接口结果作为参数)
//默认串行请求接口
mainScope.launch{
Log.d("lyy", "执行request1----开始:" + DateTimeHelper.format(Date(), "yyyy-MM-dd HH:mm:ss.SSS"))
val request1 = apiService.getDiscoverData(map)
Log.d("lyy", "执行request2----开始:" + DateTimeHelper.format(Date(), "yyyy-MM-dd HH:mm:ss.SSS"))
val request2 = apiService.getDiscoverData(map)
//需要手动处理异常情况
mainDiscoverData.value = request1.data
responseDiscoverFailData.value = false
}
请求接口时间:
//请求接口时间
执行request1----开始:2023-03-15 11:26:34.527
执行request2----开始:2023-03-15 11:26:35.432
参考:https://blog.csdn.net/yuzhiqiang_1993/article/details/101022254