Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make synchronous call in Coroutine

I want to make my network request synchronous because the input of second request comes from the output of first request.

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

In my fakeApiRequest(),I am making two network request.

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

Since,this is an asynchronous call,I am getting Null Pointer Exception in my getResult2FromApi(result1) method because the argument passed is null.

In order to fix this issue,I had to add delay(1500) in first call.

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
}

Is there anyway I can make this synchronous, so that I don't have to pass any delay time.

like image 407
Hritik Gupta Avatar asked Oct 16 '22 09:10

Hritik Gupta


1 Answers

You haven't implemented the suspendable function correctly. You must use 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)
        }
    })
}

Now your function is synchronous and returns a Geo object.

like image 91
Marko Topolnik Avatar answered Oct 20 '22 05:10

Marko Topolnik