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

一、前言:

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

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,951评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,606评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,601评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,478评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,565评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,587评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,590评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,337评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,785评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,096评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,273评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,935评论 5 339
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,578评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,199评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,440评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,163评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,133评论 2 352