-
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
Request: Map MutableStateFlow to StateFlow #2514
Comments
This has been discussed in #2008. Looks like the current way to deal with this is by using |
What if for instance we need to expose the We can't hold a |
@andreimesina you can use a scope that matches the lifecycle of your repositories. In my case, the repositories are singletons, scoped to the whole application, and thus I use Alternatively you can just construct your own If (Every My personal suggestion would be to build your architecture around the scopes automatically provided by |
@andreimesina by the way, why not just using |
@psteiger So we cannot do
Because there is no |
It is indeed not there because it has a lot of open design questions. E.g. who should invoke the As the potential solution, I'd recommend either using
|
@qwwdfsad Basic delegation is not very good solution since |
something like that?
|
Looks to me this is roughly (if not exactly) equivalent to: val stateFlow = originalStateFlow
.map { mapper(it) }
.stateIn(
coroutineScope,
SharingStarted.Eagerly,
mapper(originalStateFlow.value)
) |
Yes it is the same, I did not know this version of stateIn, the others are suspend fun and these are not suitable for use with Compose and the collectAsState fun. So we could opt for a solution like this to compact the expression:
|
Please note that although @qwwdfsad's mapped flow appears to work fine, it has a critical flaw that makes it behave differently than a real state flow, namely that only distinct items are emitted. So for example, if you have an upstream that emits a number and a downstream that emits if it's even or not, changing the upstream from An improved version might be: private class MappedStateFlow<T, R>(
private val upstream: StateFlow<T>,
private val mapper: (T) -> R,
) : StateFlow<R> {
override val replayCache: List<R>
get() = listOf(value)
override val value: R
get() = mapper(upstream.value)
override suspend fun collect(collector: FlowCollector<R>): Nothing {
var previous: Any? = Unset
upstream.collect {
val value = mapper(it)
if (value != previous) {
previous = value
collector.emit(value)
}
}
}
private object Unset
} |
@ansman I really like that solution. I recommend pairing it with a public extension function so it can be used everywhere without knowing about the wrapper class fun <T, R> StateFlow<T>.stateMap(transform: (T) -> R): StateFlow<R> {
return MappedStateFlow(this, transform)
} A couple differences from the built-in |
Hi, I am trying to convert the generic type of a
MutableStateFlow
and expose it as aStateFlow
using themap
operator.Unfortunately,
map
can only return aFlow<R>
:I also imagine that adding
as StateFlow<Group
after themap
isn't really a good idea.So, is there any solution for this case right now, or can we have a
map
that returnsStateFlow
?The text was updated successfully, but these errors were encountered: