https://kotlinlang.org logo
#android
Title
# android
c

Colton Idle

08/05/2022, 3:16 AM
I'm still very much learning about coroutines (and the difference between dispatchers vs threads) but I always found the fact of why viewModelScope.launch uses the main thread by default as an interesting choice. I suppose the answer in this SO question make sense, but does anyone have a more canonical answer as to why main dispatcher is used? https://stackoverflow.com/questions/62166878/why-does-viewmodelscope-launch-run-on-the-main-thread-by-default
r

Robert Williams

08/05/2022, 8:41 AM
Helps to remember a fundamental principle of suspend funs - they should always be main-safe https://developer.android.com/kotlin/coroutines/coroutines-best-practices#main-safe
3
Or more generally, they shouldn't block the calling thread (this it literally why suspending exists) and so caller doesn't care which thread it calls on
Given that there's no reason not to use main in ViewModelScope because it's already the thread you want to be on to do any UI stuff
(if your suspend funs are doing stuff that’s not main-safe that’s not ViewModel’s problem and you should rewrite them to suspend but if you’re just using libraries like Room or Retrofit this will already be handled)
1
c

Colton Idle

08/05/2022, 12:16 PM
Makes sense. So in the case of me writing a callBack flow that's why it's good practice for me to use flowOn? example:
Copy code
fun getBooks(): Flow<List<Book>> {
  return callbackFlow {
    val listener =
      FirebaseFirestore.getInstance()
        .collection("books")
        .addSnapshotListener { value, error ->
          trySend(value to error)
        }
    awaitClose { listener.remove() }
  }
  .doSomethingWithNullValueAndError() // Depends. It might be better after conflate
  .conflate()
  .map { (value, _) -> 
    value.toObjects()
  }
  .flowOn(defaultDispatcher)
So with the callBack flow example... firestore handles the threading... and then the cpu bound .map is offloaded to a different dispatcher via flowOn. Okay. I think as a whole my entire project is starting to make a lot more sense now. Thanks @Robert Williams for teaching!
r

Robert Williams

08/05/2022, 12:24 PM
Exactly, with flows it's the collection code that needs to be main-safe but that typically involves walking back through the full chain of operators which built the flow
👍 1
flowOn will suspend collection on main while the rest of the flow is collected on a different thread
👍 1
e

ephemient

08/05/2022, 2:28 PM
viewModelScope is not just Dispatchers.Main, it's Dispatchers.Main.immediate. which means that if you're already on the main thread, launched coroutines will be run immediately (up until a suspension point) instead of being posted to the next frame
2 Views