parth
10/13/2021, 2:44 PMMutableStateFlow
. Looks something like this:
fun whatever() {
viewModelScope.launch {
inputFlow
.map {...}
.collect { value ->
mutableStateFlow.value = value
}
}
}
(Assume that I need to push other values into the MSF
outside this collect
block)
One issue I’ve run into with the above construction is that when the observer of the MSF
cancels collection (e.g. the Fragment observing the ViewModel falls off the screen), it doesn’t cancel this intermediate collection…this makes absolute sense — that cancellation signal is not being propagated upstream!
So digging into the stateIn
sources, I’ve come up with what I think is a way to push the cancellation “upstream” — can y’all give thoughts/comments/suggestions on the following approach?
fun <T> Flow<T>.stateInto(downstream: MutableStateFlow<T>, scope: CoroutineScope) {
val upstream = this
scope.launch {
downstream.subscriptionCount
.mapLatest { count -> //this is a simplified version of [StartedWhileSubscribed#command]
if (count > 0) true
else {
delay(800.milliseconds)
false
}
}
.dropWhile { active -> !active }
.distinctUntilChanged()
.collectLatest { active ->
when (active) {
true -> upstream.collect(downstream) //will be cancelled upon new emission
false -> Unit /*just cancel and do nothing*/
}
}
}
}
darkmoon_uk
10/15/2021, 1:36 AMmutableStateFlow
is..value =
?inputFlow
mutableStateFlow
no longer mutable, but instead an immutable outputFlow
val outputFlow: Flow<SomeType> = inputFlow.map { ... } // What about the other inputs?
merge
or combine
these together.parth
10/15/2021, 1:58 AMFlow.stateIn(...)
darkmoon_uk
10/15/2021, 2:21 AMNick Allen
10/19/2021, 4:04 AMprivate val nonInputStateFlow = MutableStateFlow<ValueType>
val outputFlow = merge(inputFlow.map {...}, nonInputStateFlow)
fun otherMethod1(value: Value) {
otherMethodFlow.tryEmit(value)
}
fun otherMethod2(somethingElse: SomethingElse) {
otherMethodFlow.tryEmit(calculateValue(somethingElse))
}