Hritik Gupta
Hritik Gupta

Reputation: 632

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.

Upvotes: 5

Views: 3555

Answers (1)

Marko Topolnik
Marko Topolnik

Reputation: 200158

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.

Upvotes: 3

Related Questions