StateFlow 在一个协程中收集
StateFlow collects in one coroutine
我尝试在一个协程中初始化三个收集,但只在第一个工作。
只有当我在不同的协同程序中设置收集它的工作时。为什么?
lifecycleScope.launch {
launch {
homeViewModel.dateStateFlow().collect { date ->
date?.let { calendar.text = date.toStringForView() }
}
}
launch {
homeViewModel.toStateFlow().collect { to ->
to?.let { cityTo.text = to.name }
}
}
launch {
homeViewModel.fromStateFlow().collect { from ->
from?.let { cityFrom.text = from.name }
}
}
}
StateFlow 永远不会完成,因此收集它是一个无限的动作。 the documentation of StateFlow 中对此进行了解释。协程是顺序的,因此如果您在 StateFlow 上调用 collect
,将永远到达协程中该调用之后的代码的 none。
由于收集 StateFlows 和 SharedFlows 来更新 UI 是很常见的事情,所以我使用这样的辅助函数来使它更简洁:
fun <T> LifecycleOwner.collectWhenStarted(flow: Flow<T>, firstTimeDelay: Long = 0L, action: suspend (value: T) -> Unit) {
lifecycleScope.launch {
delay(firstTimeDelay)
lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
flow.collect(action)
}
}
}
// Usage:
collectWhenStarted(homeViewModel.dateStateFlow()) { date ->
date?.let { calendar.text = date.toStringForView() }
}
我尝试在一个协程中初始化三个收集,但只在第一个工作。 只有当我在不同的协同程序中设置收集它的工作时。为什么?
lifecycleScope.launch {
launch {
homeViewModel.dateStateFlow().collect { date ->
date?.let { calendar.text = date.toStringForView() }
}
}
launch {
homeViewModel.toStateFlow().collect { to ->
to?.let { cityTo.text = to.name }
}
}
launch {
homeViewModel.fromStateFlow().collect { from ->
from?.let { cityFrom.text = from.name }
}
}
}
StateFlow 永远不会完成,因此收集它是一个无限的动作。 the documentation of StateFlow 中对此进行了解释。协程是顺序的,因此如果您在 StateFlow 上调用 collect
,将永远到达协程中该调用之后的代码的 none。
由于收集 StateFlows 和 SharedFlows 来更新 UI 是很常见的事情,所以我使用这样的辅助函数来使它更简洁:
fun <T> LifecycleOwner.collectWhenStarted(flow: Flow<T>, firstTimeDelay: Long = 0L, action: suspend (value: T) -> Unit) {
lifecycleScope.launch {
delay(firstTimeDelay)
lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
flow.collect(action)
}
}
}
// Usage:
collectWhenStarted(homeViewModel.dateStateFlow()) { date ->
date?.let { calendar.text = date.toStringForView() }
}