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

Erik

04/21/2021, 7:08 PM
Let me rephrase my question (https://kotlinlang.slack.com/archives/C1CFAFJSK/p1619021225012300) with a runnable code example: https://pl.kotl.in/guoP8yGMg The output:
Copy code
Getting value
tick 100
tick 200
0
tick 300
tick 400
1
Got value
tick 500
tick 600
A2
tick 700
tick 800
A3
tick 900
tick 1000
A4
The desired output
Copy code
Getting value
tick 100
tick 200
0
tick 300
tick 400
1
Got value
A1 // <-- immediately emit and combine the value and the last emission from the upstream flow
tick 500
tick 600
A2
tick 700
tick 800
A3
tick 900
tick 1000
A4
Ping @baxter who showed interest in my previous thread
The issue is that the code looks very inefficient, and it likely is. And it is bugged if the suspending function returns more quickly than the first
flow
emission
b

baxter

04/21/2021, 7:48 PM
So I came up with this solution: https://pl.kotl.in/N6LC2kciE
Basically, taking the result of
foo()
and setting it on a
StateFlow
, then using
combine
. Since the initial value of the state flow is
null
, we just emit as normal, but as soon as
foo()
is complete, the state flow will emit the change.
You may even be able to do this exact same thing using:
Copy code
val fooFlow = flow {
  emit(null)
  emit(foo())
}
and combining on that flow (instead of using state flow)
e

Erik

04/21/2021, 8:10 PM
Nice, almost there! Try to change
val isGetValueSlow = true
to
false
.... It means that
foo
is fast, but you can see ticks before the first value from
foo
is collected. I'd like to collect the first value from
foo
ASAP if it comes first
b

baxter

04/21/2021, 8:14 PM
Have your
flow
emit
null
on start, and only emit the item that has a value, or both
The gist of it is that you have both flows emit
null
, but only return the one that has a non-null value. If both are non-null, emit your combined value. If both are null, just filter it out.
e

Erik

04/21/2021, 8:32 PM
Meanwhile I made my own implementation, and I think it works, but it's not very nice. The magic happens in the custom operator function... https://pl.kotl.in/TpsJd1Sjq
I'll have to look at your work in more detail too, tomorrow
Thanks for looking into it!
Note that I think that both your and my implementations don't work if
T
in
Flow<T>
or
foo(): T
is nullable
In my operator that can be mitigated by using a
val x = mutableListOf<T>()
instead of a
lateinit var
to store the provided and last value, but that's yet another inefficiency
u

uli

04/22/2021, 8:04 PM
How about channelFlow/Scan? https://pl.kotl.in/B7Bziuk0D
e

Erik

04/23/2021, 3:52 PM
Thanks for the help folks. I've now found a good solution based on all your insights that works well for my use case
u

uli

04/23/2021, 7:52 PM
care to share?
3 Views