在不发送给收集器的情况下更新 MutableStateFlow
Updating MutableStateFlow without emitting to collectors
在一个 Android 项目中,我们目前正在尝试在我们的视图模型中从 LiveData
切换到 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
标志并将其切换 on/off 以暂时禁用发射。
如果您需要公开 StateFlow
而不仅仅是 Flow
,这应该也是可能的,但您需要决定忽略的排放是否会影响其 value
。
如果您不需要在任何地方对真实状态做出反应,而只需要对公开发出的状态做出反应,我会将真实状态直接存储在 属性 中,而不是 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
}
}
如果您确实需要对其做出反应,包装器 class 和过滤(@broot 的解决方案)的一种替代方法是简单地保留两个独立的 StateFlow。
在一个 Android 项目中,我们目前正在尝试在我们的视图模型中从 LiveData
切换到 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
标志并将其切换 on/off 以暂时禁用发射。
如果您需要公开 StateFlow
而不仅仅是 Flow
,这应该也是可能的,但您需要决定忽略的排放是否会影响其 value
。
如果您不需要在任何地方对真实状态做出反应,而只需要对公开发出的状态做出反应,我会将真实状态直接存储在 属性 中,而不是 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
}
}
如果您确实需要对其做出反应,包装器 class 和过滤(@broot 的解决方案)的一种替代方法是简单地保留两个独立的 StateFlow。