【问题标题】:How to make synchronous call in Coroutine如何在协程中进行同步调用
【发布时间】:2020-02-23 22:05:32
【问题描述】:

我想让我的网络请求同步,因为第二个请求的输入来自第一个请求的输出。

override fun onCreate(savedInstanceState: Bundle?) {

retrofit1 =Retrofit.Builder()
        .baseUrl("https://jsonplaceholder.typicode.com/").addConverterFactory(GsonConverterFactory.create()).build()

retrofit2 =Retrofit.Builder()
        .baseUrl("https://samples.openweathermap.org/").addConverterFactory(GsonConverterFactory.create()).build()

button.setOnClickListener { view ->
CoroutineScope(IO).launch {
fakeApiRequest()
}}

在我的 fakeApiRequest() 中,我发出了两个网络请求。

private suspend fun fakeApiRequest() {
val result1 :Geo?= getResult1FromApi()
val result2: Long? = getResult2FromApi(result1)}

由于这是一个异步调用,我的 getResult2FromApi(result1) 方法中出现空指针异常,因为传递的参数为空。

为了解决这个问题,我不得不在第一次通话中添加延迟(1500)。

private suspend fun getResult1FromApi(): Geo? {
val service:CallService = retrofit1!!.create(CallService::class.java)
val call = service.getUsers()
call.enqueue(object : Callback<List<User>> {
override fun onResponse(call: Call<List<User>>, response: Response<List<User>>) {
g = users.get(0).address.geo
}
override fun onFailure(call: Call<List<User>>, t: Throwable) {

}
})
delay(1500)
return g
}

-----------------------------------------------------------

private suspend fun getResult2FromApi(result1: Geo?): Long? {
val service2:CallService = retrofit2!!.create(CallService::class.java)
val call2 = service2.getWeather(result1?.lat!!, result1.lng,"b6907d289e10d714a6e88b30761fae22")
call2.enqueue(object : Callback<WeatherData> {
override fun onResponse(call: Call<WeatherData>, response: Response<WeatherData>) {

}
override fun onFailure(call: Call<WeatherData>, t: Throwable) {
}
})
return dt
}

无论如何我可以使这个同步,这样我就不必经过任何延迟时间。

【问题讨论】:

  • 这很奇怪。挂起函数默认是同步的。除非你的 getResult1FromApi 有问题。您应该返回 Geo 而不是 Geo?
  • 我怀疑您对 suspend funs 的实施已关闭。你能展示你的完整代码吗?

标签: android coroutine kotlin-coroutines


【解决方案1】:

您没有正确实现可挂起功能。你必须使用suspendCoroutine:

suspend fun getResult1FromApi(): Geo? = suspendCoroutine { continuation ->
    val service = retrofit1!!.create(CallService::class.java)
    service.getUsers().enqueue(object : Callback<List<User>> {
        override fun onResponse(call: Call<List<User>>, response: Response<List<User>>) {
            continuation.resume(response.result.getOrNull(0)?.address?.geo)
        }
        override fun onFailure(call: Call<List<User>>, t: Throwable) {
            continuation.resumeWithException(t)
        }
    })
}

现在您的函数是同步的并返回一个Geo 对象。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-03-29
    • 2021-06-10
    • 1970-01-01
    • 1970-01-01
    • 2019-02-23
    • 1970-01-01
    • 1970-01-01
    • 2018-05-16
    相关资源
    最近更新 更多