https://kotlinlang.org logo
Title
s

Sudhir Singh Khanger

06/28/2021, 2:13 PM
What are possible negatives of running a
Retrofit
call without suspend keyword from a
Coroutine
?
u

uli

06/28/2021, 2:39 PM
It would block a thread. Threads are expensive and for the built in dispatchers they are a limited reessource which could be exhausted. Why would you choose to use the blocking call in the first place?
3
i

Ian Lake

06/28/2021, 3:14 PM
Also it means your request won't be automatically cancelled when the coroutine scope is cancelled; it'll just continue to be blocked
s

Sudhir Singh Khanger

06/28/2021, 4:14 PM
1. Would it block main thread? 2. Will it still block main thread if I called it using Dispatchers.IO? 3. In the following case will
someOtherFunction()
not be called if I don't use
suspend
function?
viewModelScope.launch {
launch { non-suspending-retrofit }
someOtherFunction()
}
4. In a scope everything is already synchronous so even if it blocks the non-ui thread I am not sure if that matters. Enlighten me please. 5. Is logging the best way to detect blocking calls?
z

Zach Klippenstein (he/him) [MOD]

06/28/2021, 5:15 PM
1. It will block whatever thread you’re calling it from, i.e. whatever thread the coroutine is “running” on when you call it. If that’s the main thread, then you’ll block the main thread. 2. No. 3. Since you’re already in a coroutine, the inner coroutine will not start immediately but be enqueued, so
someOtherFunction()
will run first and then one the coroutine starts, then it will block its thread. 4. A good rule is that the only time it’s safe to block a coroutine for IO work is if you’re running on the IO dispatcher. 5. Logging won’t automatically detect blocking calls. I don’t know of any generic way to detect blocking calls other than mechanisms very specific to Android’s main thread (i.e. ANR detection).
g

gildor

06/28/2021, 11:41 PM
I believe Retrofit2 doesn't support blocking calls out of the box, though it's possible to write custom adapter for this. But the real question is why do you need this?
z

Zach Klippenstein (he/him) [MOD]

06/28/2021, 11:57 PM
Yea, this all seems like kind of a pointless discussion – just make your retrofit interface use suspend functions.
j

jw

06/29/2021, 1:42 AM
@gildor it does. Call.execute()
g

gildor

06/29/2021, 2:35 AM
Ah yeah, sorry for confusion, I meant if you just drop
suspend
to return result directly, without Call
1
j

jw

06/29/2021, 2:40 AM
right. that will not work out of the box, but like you said you could make it work!
s

Sudhir Singh Khanger

06/29/2021, 9:03 AM
But the real question is why do you need this?
this all seems like kind of a pointless discussion
I am not using Retrofit in a Coroutine without
suspend
keyword. I was asked as to why I have marked a function as
suspend
when I could use it without one. I wish I could just say to just use it because it is a good thing. I need to justify its usage with code and solid argument. I can't present it like a black magic.
g

gildor

06/29/2021, 9:06 AM
Well, it’s good enough explanation, that you should justify usage of coroutines. Another question what you are comparing, suspend vs Call?
s

Sudhir Singh Khanger

06/29/2021, 9:16 AM
No, I am comparing a retrofit call method with and without
suspend
keyword.
g

gildor

06/29/2021, 9:21 AM
But it doesn’t work out of the box without suspend keyword, if you just remove suspend it will not work
1
z

Zach Klippenstein (he/him) [MOD]

06/29/2021, 11:09 AM
To Andrey’s point about suspend vs
Call
, i think your question could be interpreted to be about two different things: 1. What’s the difference between synchronous, blocking APIs and asynchronous, non-blocking ones? Eg
Call.execute
vs
Call.enqueue
2. What’s the difference between using coroutines for asynchronous requests vs other async apis like
Call.enqueue
? With your clarification, if I understand correctly, it sounds like you’re not really asking about retrofit specifically, and your question is more (1), ie “Why use an API that allows for non-blocking asynchrony vs one that blocks?” That is a pretty large question but one that has been discussed extensively. In Java (and many other programming languages), the answer basically comes down to “because OS threads are expensive and it’s a lot cheaper and more flexible to manage asynchrony in userspace”. In most traditional languages the only way to do this is via callbacks, but languages like Kotlin, Swift, Python, C#, etc have all introduced various forms of syntactic sugar (eg coroutines, async/await) to make working with callbacks easier and less boilerplatey and support stuff like cancellation.