I'm curious... for those who work at a tech compan...
# android
r
I'm curious... for those who work at a tech company where there's some sort of "architecture", where does threading fit into all that? I'm curious at what layer in your architecture you switch threads (if you switch at all :)). Also, how are your threads set up? Do you have your own thread pools? Do you use given thread pools (Like
<http://Dispatchers.IO|Dispatchers.IO>
in coroutines)? Do you do things asynchronously or more blocking? Damn I got a lot of questions haha
1
s
I would like to see source code of a large scale app with millions of user base and a whole team working/developing it .... I would like to see how things in android dev work altogether in a large scale app , is it or is it not the same as a normal app , what extra practices they use if any.... And i believe see something in action answers more questions than we had at the moment , we learn more..... If anybody knows of anysuch such project's repo , i would be very grateful!
👍 1
o
I work in multiple code bases, some really really large and some that are small/simple. The architectures are pretty close, mainly MVVM, some with a flavor of MVI. But what is consistent across all these codebases in terms of threading, is that all methods within the view (activity/fragment) and ViewModel are main-safe. That is, you can call all methods safely on main thread and won't block the UI. Using the repository/useCase pattern, public methods contained in this classes should also be main safe. It's recommended to pass the different dispatchers into your repo/useCase classes so you can easily test as well. But the main thing to point out here is that all public methods are main-safe. Thread switching (using Dispatchers.IO, Dispatchers.Default etc) is contained within the repository/use case classes. Whether it be calling some remote data source, db, or data processing etc. Coroutines and some helpful extensions like viewModelScope make this all clean and easy to achieve. So an example would be a suspend method loadUsers in the repo, which is main-safe, since it internally uses withContext to switch to Dispatchers.IO for loading users. I'm probably giving an over simplification here but I think you get the picture I'm trying to paint 😊. Idk if this exactly answers all or some of your questions.. 2a.m. here and I'm struggling to fall asleep haha but my brain is a bit fried atm. Just came across this and thought I'd share what I typically do. Edit: just want to clarify that what I explained above is more a general pattern. It's acceptable to use Dispatchers.Default for example, even in your ViewModel. I think the most important rule is more that any public method is main-safe. And if you follow the architecture j described above, the view will be as dumb/simple as possible, so there is no need to handle thread switching in the view layer. The ViewModel contains straightforward business logic, such as retrieving data from repo layer and managing/updating a state, so there's really no need to handle thread switching here as well. Which then brings the last part which is your data/repo layer. Which basically exposes public main-safe APIs, but internally that is where thread switching/if any, is typically happening. Which is typically the case, fetching data from web service, local db, mapping Backend models etc. Hope that clears up any additional confusion.
👍 1
v
We use
Executors.newSingleThreadExecutor().asCoroutineDispatcher()
on our use case layer to make sure that domain objects are not modified concurrently, otherwise, normal coroutine stuff you see everywhere: IO for IO, UI for UI etc..
👍 1
z
I work on a pretty large codebase, and most code isn’t concerned about threading. Retrofit handles threading for network requests, and we do database operations on a different thread (we use a single background “file” thread for most DB ops). But most of our business logic is ran on the main thread - we actually try to get back there as quickly as possible, @Ray Ryan gave a

talk

about why some years ago. We use the standard Rx schedulers and coroutine dispatchers, but all access to them is done via injection with dagger. Certain features have specific, unique threading requirements and they do their own thing, but that’s rare.
1
👍 1
j
For coroutines I think it is best-practice to have the place where the work is happening take care of threading. For example, if you have Room you should be able to interact with coroutines and room from the main thread, because room will internally switch to IO. Same goes for retrofit and it SHOULD work like this with other libraries as well
doesn't mean all libraries cohere to this best-practice
even though they should