Android 正在覆盖的可变状态流事件
在MyViewModel中,使用可变状态流将事件传输到片段。 当MutableStateFlow的值更改时,早期的值将在协同例程中被覆盖。所以从未收到过碎片Android 正在覆盖的可变状态流事件,android,kotlin,coroutine,stateflow,Android,Kotlin,Coroutine,Stateflow,在MyViewModel中,使用可变状态流将事件传输到片段。 当MutableStateFlow的值更改时,早期的值将在协同例程中被覆盖。所以从未收到过碎片 internal class MyViewModel(application: Application) : AndroidViewModel(application) { private val myMutableStateFlow = MutableStateFlow<MySealedClass>(MySealedC
internal class MyViewModel(application: Application) : AndroidViewModel(application) {
private val myMutableStateFlow = MutableStateFlow<MySealedClass>(MySealedClass.Dummy1())
private fun getData() {
viewModelScope.launch {
//yield()
myMutableStateFlow.value = MySealedClass.Dummy2()
myMutableStateFlow.value = MySealedClass.Dummy3()
}
}
}
internal class MyFragment : Fragment(){
private var uiStateJob: Job? = null
override fun onStart() {
super.onStart()
uiStateJob = lifecycleScope.launch {
myViewModel.getUiFlow().collect {
//do something
}
}
}
}
内部类MyViewModel(应用程序:应用程序):AndroidViewModel(应用程序){
private val myMutableStateFlow=MutableStateFlow(MySealedClass.Dummy1())
私有数据{
viewModelScope.launch{
//收益率()
myMutableStateFlow.value=MySealedClass.Dummy2()
myMutableStateFlow.value=MySealedClass.Dummy3()
}
}
}
内部类MyFragment:Fragment(){
私有变量uiStateJob:作业?=null
覆盖有趣的onStart(){
super.onStart()
uiStateJob=lifecycleScope.launch{
myViewModel.getUiFlow().collect{
//做点什么
}
}
}
}
如果对yield()进行了注释,则片段永远不会收到Dummy2事件。但收到了虚拟3。
如果yield()未注释,则会同时收到Dummy2和3。
如果状态值在协同程序外更改,则同时接收Dummy2和Dummy3
我需要可预测地接收片段中的所有事件。
这种行为有正确的理由吗?
StateFlow
表示一种状态。从技术上讲,每个事件都是一个新的最新状态值,使以前的状态过时。这种类型的流适用于只有最新状态才重要的情况,因为它的事件是合并的。从文档中:
对值的更新始终合并。因此,较慢的收集器跳过快速更新,但始终收集最近发出的值
编辑以响应您的评论:yield()
是一个暂停函数,强制暂停当前协同程序。因此,它给了另一个协程一个机会,让它继续前进,直到下一个暂停点,这就是为什么在这种情况下,在设置(并发出)第一个值之前,collect是“就绪”的
但是,您不应该依赖它,因为它很脆弱:如果另一个协同程序被修改,并且通过调用其他挂起函数具有额外的挂起点,它可能无法到达collect
调用,您将返回到另一个行为
如果您始终需要所有事件,您有几个选项:
- 切换到冷流,仅在收集时启动
- 使用
(带或不带缓冲区)频道
- 使用
并通过使用订阅上的SharedFlow
onSubscription来触发事件启动