android - 如何在协程中进行同步调用
问题描述
我想让我的网络请求同步,因为第二个请求的输入来自第一个请求的输出。
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
}
无论如何我可以使这个同步,这样我就不必通过任何延迟时间。
解决方案
您没有正确实现可挂起功能。您必须使用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
对象。
推荐阅读
- javascript - 用复选框控制 javascript
- java - 创建具有多个客户端的服务器
- c++ - 模板实例化是解析 C++ 的一部分吗
- python - 返回小于等于日期的最近外键的子查询
- flutter - 未处理的异常 ScrollController 未附加到任何滚动视图
- java - 内存中的非序列化对象会发生什么?
- java - 如何在fire base android中同时在一个节点的两个子节点上写入数据?
- model-view-controller - 如何在 Joomla 的前端部分使用编辑和保存按钮创建列表视图!3 成分?
- c# - 如何在 C# 中调用/编组 C++“const uint64_t*”?
- javascript - 获取销售日期可变产品 woo