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

xxfast

07/06/2021, 11:53 PM
Hi all - is there a
Flow<T>.flowOn(dispatcher)
equivalent that that affects downstream? so that i can do
Copy code
results
  .map { result -> format(result) }
  .flowOn(<http://Dispatchers.IO|Dispatchers.IO>)
  .collectOn(Dispatchers.Main)
  .collect { presenter.display(it) }
instead of
Copy code
withContext(Dispatchers.Main) { 
  results
    .map { result -> format(result) }
    .flowOn(<http://Dispatchers.IO|Dispatchers.IO>)
    .collect {
      presenter.display(it)
    }
}
s

streetsofboston

07/07/2021, 12:02 AM
What about:
Copy code
withContext(Dispatchers.Main) {
  results
    .map { result -> format(result) } 
    .flowon(<http://Dispatchers.IO|Dispatchers.IO>)
    .collect { ... }
}
since
collect
is a suspending function
u

ursus

07/07/2021, 12:15 AM
scope you run in is your downstream "thread"
n

Nick Allen

07/07/2021, 12:19 AM
flowWith
used to exist as part of the Flow preview library but was removed because it didn't play well with other coroutine/flow semantics.
If you simply want to avoid the nesting:
Copy code
results
  .map { result -> format(result) }
  .flowOn(<http://Dispatchers.IO|Dispatchers.IO>)
  .onEach { presenter.display(it) }
  .flowOn(Dispatchers.Main)
  .collect()
❤️ 1
x

xxfast

07/07/2021, 2:55 AM
yeah i prefer less nesting - and like @Nick Allen’s one the most
is there a negative connotation of using
.onEach
instead of
.collect
?
e

ephemient

07/07/2021, 3:58 AM
no, it's also the only reasonable way to use
.launchIn(scope)
m

myungpyo.shim

07/07/2021, 8:42 AM
If you are using it in Android ViewModel, you can use launchIn like below. (as ephemient mentioned above)
Copy code
private fun sample1() {
    membershipUiData
        .map { /* IO Thread */ }
        .flowOn(<http://Dispatchers.IO|Dispatchers.IO>)
        .onEach { data ->
            /* Main thread */ 
        }
        .launchIn(viewModelScope)
}

private suspend fun sample2() = viewModelScope.launch {
    membershipUiData
        .map { /* IO Thread */ }
        .flowOn(<http://Dispatchers.IO|Dispatchers.IO>)
        .collect { data ->
            /* Main thread */
        }
}
(viewModelScope is composed of Dispatchers.main.immediate + SupervisorJob. So, if you are not using ViewModel, you can define appropriate context by yourself.)
e

ephemient

07/07/2021, 9:10 AM
but consider
Copy code
viewLifecycleOwner.repeatOnLifecycle(STARTED) {
    flow.collect { ... }
}
instead, https://medium.com/androiddevelopers/a-safer-way-to-collect-flows-from-android-uis-23080b1f8bda
4 Views