美文网首页Android进阶
Android协程中同时请求多个网络接口

Android协程中同时请求多个网络接口

作者: 因为我的心 | 来源:发表于2023-03-14 10:18 被阅读0次

一、前言:

我们在开发过程中,很可能会遇到这样的需求,一个页面中需要同时请求好几个接口。

作用域学习: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)
}

下面我们来运行看看执行结果:

图片.png

总结:在协程作用域中请求使用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)
}
图片.png

可以看到我们得到了想要的结果。

总结:在协程作用域中接口的执行顺序是串行的,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

相关文章

网友评论

    本文标题:Android协程中同时请求多个网络接口

    本文链接:https://www.haomeiwen.com/subject/yhzvldtx.html