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

fal

03/19/2021, 12:45 AM
Hi, I'm learning coroutines (coming from Rx world) and I'm trying to find a good way to refresh my flows on ViewModel... So far what I've been thinking is creating a shared flow to represent refresh events, something like:
Copy code
private val refreshFlow =
    MutableSharedFlow<Unit>(replay = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST).apply {
      tryEmit(Unit)
    }

init {
  fetchNews()
}

fun refreshData() {
  refreshFlow.tryEmit(Unit)
}

private fun fetchNews() {
  viewModelScope.launch {
    refreshFlow
        .flatMapLatest { fetchLatestNewsFlow() }
        ...
        .collect()
  }
Is this ok? Are there any better solutions?
e

ephemient

03/19/2021, 12:52 AM
I hope it's ok. we're doing something similar - multiple
Flow<Unit>
coming from various places,
.flattenMerge()
them all together for a single stream of "somebody wants a refresh now" triggers
👍 1
f

fal

03/19/2021, 1:08 AM
@ephemient Do your Flow<Unit>'s somehow represent UI events? Reason I'm asking is because I don't really like having hot flows for this, but I don't see how I could represent UI actions through cold flows
e

ephemient

03/19/2021, 1:09 AM
UI events and server events. how can UI events be cold? it's not like you tell the user to stop pushing buttons
f

fal

03/19/2021, 1:11 AM
Yea, I got confused by your Flow<Unit> explanation (I somehow assumed they were cold), but of course that doesn't actually specify whether they're cold or not 👍 If it's a mix between server and UI events I get it, thanks!
b

baxter

03/19/2021, 5:14 AM
Closest thing I can think of for a RxJava -> Coroutines mappings is: • If you need to use
Single
or
Maybe
, consider using a
suspend
function or just launch a single use coroutine with
launch
or
async
on a scope. • If you need a stream such as
Observable
or
Flowable
, and the stream would complete, use
flow {}
. • If the stream is hot, then use
MutableSharedFlow()
or
MutableStateFlow()
.
1
I'm guessing here, but it looks like you have a flow coming from
fetchLatestNewsFlow()
that is doing a single task (fetching the latest news and caching it). You can probably just call
fetchLatestNewsFlow().launchIn(viewModelScope)
each time you call
refreshData()
.
I would move whatever logic you have in the flow that is run each time you call
fetchLatestNewFlow()
, unwrap it from the flow block, and make that function a suspend function, so I can just do:
Copy code
fun refreshData() {
  viewModelScope.launch { fetchLatestNews() }
}
1
But that's just my 2 🪙
f

fal

03/19/2021, 10:35 AM
@baxter Thanks for the response! I definitely agree with you with your approach, and I don't think the 'fetchLatestNews()' was the best example, since it does imply that a simple suspend function would suffice. My question was a bit more general, in the sense of "what if I want to refresh flows"? Despite this, your tips are definitely helpful and make sense to avoid building flows when they're not necessary 👍
4 Views