在一个Android项目中,我们目前正试图在视图模型中从LiveData
切换到StateFlow
。但对于一些罕见的情况,我们需要在不通知收集器更改的情况下更新状态。当我们想到流的工作机制时,这听起来可能很奇怪,但我想知道这是否可行。任何真正的解决方案或变通方法都将不胜感激。
如果您不需要在任何地方对真实状态做出反应,而只需要对公开发出的状态做出响应,我会直接将真实状态存储在属性中,而不是MutableStateFlow。
private var trueState: MyState = MyState(someDefault)
private val _publicState = MutableStateFlow<MyState>()
val publicstate = _publicState.asStateFlow()
fun updateState(newState: MyState, shouldEmitPublicly: Boolean) {
trueState = newState
if (shouldEmitPublicly) {
_publicState.value = newState
}
}
如果您确实需要对此做出反应,那么包装类和过滤(@broot的解决方案(的一个替代方案就是简单地保留两个独立的StateFlow。
我们可以公开另一个根据需要过滤项的流,而不是直接公开状态流。
例如,我们可以将shouldEmit
标志保留在已发出的项中。或者使用任何其他过滤逻辑:
suspend fun main(): Unit = coroutineScope {
launch {
stateFlow.collect {
println("Collected: $it")
}
}
delay(100)
setState(1)
delay(100)
setState(2)
delay(100)
setState(3, shouldEmit = false)
delay(100)
setState(4)
delay(100)
setState(5)
delay(100)
}
private val _stateFlow = MutableStateFlow(EmittableValue(0))
val stateFlow = _stateFlow.filter { it.shouldEmit }
.map { it.value }
fun setState(value: Int, shouldEmit: Boolean = true) {
_stateFlow.value = EmittableValue(value, shouldEmit)
}
private data class EmittableValue<T>(
val value: T,
val shouldEmit: Boolean = true
)
我们还可以将shouldEmit
标志保留在对象中,并将其打开/关闭以暂时禁用排放。
如果您需要暴露StateFlow
而不仅仅是Flow
,这也应该是可能的,但您需要决定忽略的排放是否会影响其value
。