https://kotlinlang.org logo
#coroutines
Title
# coroutines
j

Jhonatan Sabadi

11/22/2023, 9:54 PM
Which one is better? 1. Call retrofit from viewModel than map data using ViewModelScope, knowing that retrofit create a background task 2. Uses withContext inside ViewModelScope to do all on Dispatchers.IO?
p

Pablichjenkov

11/22/2023, 10:02 PM
I normally encapsulate that operation in a UseCase
Copy code
Class UseCase<CustomResult<T>> {
  suspend execute():CustomResult<T>
}
Then consume the use case from the VM like in your point 2
1
a

andriyo

11/22/2023, 10:09 PM
I preferer to have Repository or UseCase level to do context switch to IO and mapping to domain data model. Then ViewModel doesn't know about data source and works on UI thread. ViewModel could do additional data transformation to UI specific data classes but they are usually lightweight enough to do on UI thread relying on some implicit assumptions that some code will run on non-UI thread is not cool, I think.
2
j

Jhonatan Sabadi

11/22/2023, 10:17 PM
I sow one day a video on Google q/a that they're talking about not changing context in Network/database calls. They tell is lighter do on ui thread with coroutines than changing context than back to ui.
a

andriyo

11/22/2023, 10:55 PM
it's easier for me to wrap Repo suspend methods into withContext(IO) and do all data transforms there and forget about it.
p

Pablichjenkov

11/22/2023, 11:08 PM
It is lighter for sure, no context switching but as Andrii mentioned you would have to trust the library doing the right job.
j

Jhonatan Sabadi

11/23/2023, 12:11 AM
I see. In case of map data to model could require CPU work, it's better to change context on data layer
p

Pablichjenkov

11/23/2023, 12:14 AM
That also counts
a

Anselmo Alexandre

11/23/2023, 8:07 AM
I do agree with @andriyo, switching coroutines context on data-layer it’s also helpful when it comes to tests.
j

Javier

11/23/2023, 8:20 AM
Retrofit will use IO (or Default) anyway independently you switch the context or not.
a

andriyo

11/23/2023, 8:36 AM
but if tomorrow someone replaces Retrofit with Ktor in your service talking code, that won't longer be the case. it's better to have explicit boundaries just be safe.
j

Javier

11/23/2023, 8:37 AM
Ktor uses IO or Default too. It should be weird a network library doesn’t use a dispatcher under the hood
a

andriyo

11/23/2023, 8:46 AM
why not to allow the caller to choose in what context to run network library code? it gives flexibility to run it on whatever
j

Javier

11/23/2023, 9:19 AM
The convention from coroutines is that the library author knows which is the correct implementation detail.
2
a

andriyo

11/23/2023, 3:52 PM
I understand where you're coming from and it's true that Retrofit changes execution context for its APIs ( and other data access libraries like Room for example do that too), but Ktor Client doesn't. And I don't think coroutines as such dictate in any way whether libraries should give control over execution context to clients or not. It's on library authors to design however they please.
j

Javier

11/23/2023, 3:53 PM
Well, it is explained in the coroutines docs. Of course authors can do whatever they want later
About ktor, are you sure about that? I would bet it provides a dispatcher.
a quick look at ktor show they are providing a dispatcher in its Darwin client implementation
Looks like it is using
IO
as default and it is overridden in some platforms like Darwin. https://github.com/ktorio/ktor/blob/main/ktor-client/ktor-client-core/common/src/io/ktor/client/engine/HttpClientEngineBase.kt
a

andriyo

11/23/2023, 4:10 PM
I'm pretty sure I needed to wrap it in withContext (Io)for Android, I'll check
a

andriyo

11/23/2023, 4:43 PM
I use OkHttp for my android client and it ANRs if I don't wrap Ktor client code in withContext(IO) on my side
j

Javier

11/23/2023, 4:51 PM
OkHttp client is using a different implementation
I would report it tbh
a

andriyo

11/23/2023, 4:55 PM
it's cool since it give client freedom to provide whatever dispatcher they want, at least for OkHttp engine ) but my point stands - importance of defensive use of withContext() since it's not consistent even within a single framework whether it's going to be run on UI thread or not
1
m

myanmarking

11/24/2023, 4:27 PM
retrofit just uses its own dispatcher. I just call the interface on the main thread dispatcher, and map it also in the main (if the map is fast). Otherwise i just do the mapping on IO. I never use IO to call retrofit stuff. I don’t see any point since it will use its own dispatcher ?
a

andriyo

11/24/2023, 8:07 PM
no need to retrofit especially if it's explicitly stated in their API documentation that they switch context for you
2 Views