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

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

我在之前写过一篇关于 高德逆地理编码接口返回数据格式不统一以及百度逆地理编码接口返回数据解析失败的踩坑记录 这篇文章,我当时的需求是要结合高德和百度两个接口,合并成一个我想要的数据。在文章中,我们使用了Rxjava的zip操作符来处理的两个接口同时请求的逻辑。大概代码如下:

        Observable.zip(
            editUnitInfoModel.getBaiduRegeo(location),
            editUnitInfoModel.getGaodeRegeo(location),
            BiFunction<BaiduRegeoBean, GaodeRegeoBean, LocationDetailsBean> { baidu, gaode ->
                val locationDetailsBean = LocationDetailsBean()

                if (baidu.status == 0) {
                    val baiduAddressComponent = baidu.result.addressComponent
                    locationDetailsBean.adcode = baiduAddressComponent.adcode
                    locationDetailsBean.city = baiduAddressComponent.city
                    locationDetailsBean.country = baiduAddressComponent.country
                    locationDetailsBean.district = baiduAddressComponent.district
                    locationDetailsBean.province = baiduAddressComponent.province
                    locationDetailsBean.street = baiduAddressComponent.street
                    locationDetailsBean.streetNumber = baiduAddressComponent.streetNumber
                    locationDetailsBean.town = baiduAddressComponent.town
                }

                if (gaode.status == "1") {
                    locationDetailsBean.townCode = gaode.regeocode.addressComponent.towncode
                }
                LogUtils.i("合并后的定位信息为:${locationDetailsBean}")
                return@BiFunction locationDetailsBean

            }
        )

具体实现逻辑感兴趣的可以去看看那篇文章。本篇文章中,我们来使用Kotlin协程来实现这个需求,你会发现,使用协程来处理,代码非常的简洁。


Kotlin协程处理并发

如果你对协程还不了解,建议去官网先学习一下。

这里我们使用两个方法来模拟网络请求

suspend fun one(): Int {
    delay(1500)
    return 1
}

suspend fun two(): Int {
    delay(1500)
    return 2
}

两个方法都是可挂起的方法,分别返回1和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)
}

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

在这里插入图片描述

可以看到,我们顺利的拿到了想要的结果。而且对比使用RxJava的实现方法,会发现,协程的代码会少很多,且结构更加的清晰。

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)
}

在这里插入图片描述

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

kotlin协程总结

通过这两个小例子可以发现,无论你是要实现并发还是要指定顺序的执行多个异步方法,协程都能很简洁的实现。
在实际的Android开发中,我们可以结合Retrofit2.6.0及以后的版本更加优雅的实现网络请求等异步逻辑。
我个人认为协程完全可以替代RxJava去实现异步逻辑,且代码更加简洁。

关于结合Retrofit的使用请看:Retrofit+kotlin Coroutines(协程)+mvvm(Jetpack结构组件)实现更简洁的网络请求

好了,本篇文章就是这样


如果你觉得本文对你有帮助,麻烦动动手指顶一下,算是对本文的一个认可,如果文中有什么错误的地方,还望指正,转载请注明转自喻志强的博客 ,谢谢!

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐