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

leandro

11/25/2020, 8:37 PM
I thought it would be easy because I will always have an initial value (ZonedDateTime.now()), but if that's too cumbersome I can make its consumers suspend
w

wbertan

11/25/2020, 8:39 PM
Could you use the
SharedFlow
? This week I’ve received help here and a suggestion was to use it, and for me it works as expected, here is the thread: https://kotlinlang.slack.com/archives/C1CFAFJSK/p1606233013349500?thread_ts=1606232057.348900&cid=C1CFAFJSK
l

leandro

11/25/2020, 8:46 PM
although SharedFlow does more than the StateFlow, it doesn't seem like I can sneak in some transformation to have it emit regularly 😕
w

wbertan

11/25/2020, 9:00 PM
You could use
onSubscription
🤔
Copy code
MutableSharedFlow<Long>(
    0,
    extraBufferCapacity = 1,
    onBufferOverflow = BufferOverflow.DROP_OLDEST
).onSubscription {
    while(true) {
        emit(System.currentTimeMillis())
        delay(5_000)
    }
}
e

elizarov

11/25/2020, 9:08 PM
It would not work. On subscription will suspend the whole flow. You cannot work around having to provide scope. Still, why it has to be SharedFlow? Why a regular flow does not work for you?
w

wbertan

11/25/2020, 9:25 PM
It is only recent I’ve start to look more in Coroutines, but from my test it executes either way, for example:
Copy code
class AsasTest {

    val a = MutableSharedFlow<Long>(
        replay = 0, extraBufferCapacity = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST
    ).onSubscription {
        val id = UUID.randomUUID().toString()
        println("creating flow $id")
        while (true) {
            println("emit flow $id")
            emit(System.currentTimeMillis())
            delay(5_000)
        }
    }

    @Test
    fun testAsasA() {
        runBlocking {
            a.onEach { println("a1 $it") }.launchIn(this)
            a.onEach { println("a2 $it") }.launchIn(this)
        }
    }
}
It will result in this output:
Copy code
creating flow 7e83c9c0-af30-4621-99a7-87dfc3c4fbc9
emit flow 7e83c9c0-af30-4621-99a7-87dfc3c4fbc9
a1 1606339289726
creating flow 83a59d4a-8394-49e8-b11b-ca7309917fde
emit flow 83a59d4a-8394-49e8-b11b-ca7309917fde
a2 1606339289739
emit flow 7e83c9c0-af30-4621-99a7-87dfc3c4fbc9
a1 1606339294743
emit flow 83a59d4a-8394-49e8-b11b-ca7309917fde
a2 1606339294743
emit flow 7e83c9c0-af30-4621-99a7-87dfc3c4fbc9
a1 1606339299747
emit flow 83a59d4a-8394-49e8-b11b-ca7309917fde
a2 1606339299748
I understand it would be the same as doing:
Copy code
val b = flow {
        val id = UUID.randomUUID().toString()
        println("creating flow $id")
        while(true) {
            println("emit flow $id")
            emit(System.currentTimeMillis())
            delay(5_000)
        }
    }
And my understand of the question would be how to share it to not have to “create” a new
Flow
or
SharedFlow
for each subscription, but I’ve tried in the past and still don’t know how to do it, I believe it would be something like:
Copy code
val c = flow {
        val id = UUID.randomUUID().toString()
        println("creating flow $id")
        while(true) {
            println("emit flow $id")
            emit(System.currentTimeMillis())
            delay(5_000)
        }
    }.shareIn(<What I should put here to share?>)
But I’m struggling with the
shareIn
as it is a
val
and I don’t have a
CoroutineScope
to provide it. To understand my original scenario it was to replace a Rx
Observable.share()
.
u

ursus

11/25/2020, 9:50 PM
well, you want to share state, it needs a scope however your state is basically in
now()
so ju might just prepend that value on every subscription?
onStart(emit(now())
something like that
3 Views