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

myanmarking

06/03/2020, 11:44 AM
I need advice on something:
Copy code
sealed class Updates{
    data class LiveUpdate(val progress: Int): Updates()
    data class History(val list: List<Int>): Updates()
}

private fun fetchUpdates(): Flow<Updates> {
    TODO()
}

private fun save(list: List<Updates.History>){
    TODO()
}

fun dispatchUpdates(): Flow<Updates.LiveUpdate>{
    val history = mutableListOf<Updates.History>()
    return fetchUpdates()
        .onEach { 
            if(it is Updates.History){
                history.add(it)
            }
        }
        .onCompletion { if(it != null) save(history) }
        .filterIsInstance<Updates.History>()
}
Is there any way to improve this code so that the save part doesn't end up a side-effect? Something like an inner flow. I'm not sure how to approach this
g

gildor

06/03/2020, 11:48 AM
To avoid side efffects you shouldn’t mix sideffect with this chain. and instead have 1 flow for updates and 1 for side effect:
Copy code
fun historyUpdates(): Flow<Updates.History> {
  return fetchUpdates().filterIsInstance<Updates.History>()
}

suspend fun saveHistory() {
  save(historyUpdates().toList())
}

//and some other method which want to get updates on every update, but without mixing with side effect
m

myanmarking

06/03/2020, 11:53 AM
yes, it makes sense. but parent flow is a callback flow, so i cannot duplicate the stream. I need to branch it into two independent flows, but idk how to do that
g

gildor

06/03/2020, 11:53 AM
why you cannot duplicate?
anyway, share operators are not released yet
m

myanmarking

06/03/2020, 11:54 AM
yes, thats it. cannot duplciate because i cannot have two calls to the same parent flow. won't work
g

gildor

06/03/2020, 11:54 AM
so now or start 2 flows, or use channel, or keep your existing code
cannot have two calls to the same parent flow
But why?
what if someone will do that?
or even consume your dispatchUpdates() twice?
it would be the same
m

myanmarking

06/03/2020, 11:56 AM
because its a wrapper for some ble operations. and it cannot happen at the same time. its a legacy api
i'll use a channel. its more appropriate then
g

gildor

06/03/2020, 11:56 AM
so your existing solution will not work too
I mean it doesn’t limit amount of subscribers
I would implement for now using BroadcastChannel
m

myanmarking

06/03/2020, 11:57 AM
yes, it does not
g

gildor

06/03/2020, 11:57 AM
and use asFlow() on it
so it would support multiple subscribers
and reimplement later with Flow share operator
a

ahulyk

06/03/2020, 2:28 PM
@myanmarking try
StateFlow
. I did some simple sample -> https://pl.kotl.in/CIFp67rcr
m

myanmarking

06/03/2020, 2:31 PM
ok thanks. i'll give it a try
g

gildor

06/03/2020, 11:53 PM
StateFlow will not help in this case, it will not help with laziness and cancellation, which needs you for ble events And after all StateFlow is caching the latest event, which is not what you need probably for events listening
👍 1
3 Views