-
Notifications
You must be signed in to change notification settings - Fork 1.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ConflatedBroadcastChannel should deliver last value #1816
Comments
It is the design now, but we can change it. What is your use-case for |
I just ran into the same issue. I have a class DownloadCoordinator {
private val stateChannel = ConflatedBroadcastChannel<DownloadState>(DownloadState.Initial)
val states = stateChannel.asFlow()
// etc.
} Emitting looks like this:
Now a consumer that's interested in the latest state of the download simply does this: downloadCoordinator.states.first() It was totally unexpected to me that
I've expected the flow to re-emit the last value. I also have other consumers that use From the docs:
"most recently sent element/value" is mentioned three times.
|
Thanks for the detailed explanation! |
StateFlow is a Flow analogue to ConflatedBroadcastChannel. Since Flow API is simpler than channels APIs, the implementation of StateFlow is simpler. It consumes and allocates less memory, while still providing full deadlock-freedom (even though it is not lock-free internally). Fixes #1973 Fixes #395 Fixes #1816
It is being provided by implementation in #1974 |
@elizarov Sorry for late reply in these difficult times Anyway, my point was that Now, you can close the issue if you will, but in my opinion it is not resolved. Neither |
@pacher As discussed in |
@elizarov No I can't, because then final result will not be included, which is a bummer. For implementation I copy-pasted if (predicate(value)) emit(value)
else throw AbortFlowException(this) to emit(value)
if (predicate(value)) throw AbortFlowException(this) But it would be really nice to have it in the library (even simple
Yes, I got your point in #2034 that materializing is the way to go, which I still think is a workaround (and not only me). I would rather say: " While we are waiting for proper operators in the library, can you please have a look at this naive implementation of dematerialize? sealed class Event<T> {
class Emission<T>(val item: T) : Event<T>()
class Error(val error: Throwable) : Event<Nothing>()
object Complete : Event<Nothing>()
}
fun <T> Flow<Event<T>>.dematerialize(): Flow<T> =
takeWhile { it !is Complete }
.map {
when(it) {
is Emission -> it.item
is Error -> throw it.error
Complete -> error("Can not happen")
}
} Is it usable? Is it idiomatic just to throw from P.S. Again, the issue was not about my use case, but about consistency between |
@pacher Good point. Thanks. See #2042
This implementation looks good to me and it is quite idiomatic. It is similar to what we'll write if we make a decision to include that kind of operator into the library. |
We've decided to add |
StateFlow is a Flow analogue to ConflatedBroadcastChannel. Since Flow API is simpler than channels APIs, the implementation of StateFlow is simpler. It consumes and allocates less memory, while still providing full deadlock-freedom (even though it is not lock-free internally). Fixes Kotlin#1973 Fixes Kotlin#395 Fixes Kotlin#1816 Co-authored-by: Vsevolod Tolstopyatov <qwwdfsad@gmail.com>
For
ConflatedChannel
the problem was discussed in #332, addressed in #1235 and fixed by #1239,but not for
ConflatedBroadcastChannel
Slightly modified example from #1235:
Correctly prints
4
, butthrows
ClosedReceiveChannelException
Is it by design?
The text was updated successfully, but these errors were encountered: