Hay*_*yan 2 android kotlin kotlin-coroutines
在我的应用程序中,我有一个 UIState 密封类来表示 UI 状态。
sealed class UIState<T> {
class ShowLoading<T> : UIState<T>()
class HideLoading<T> : UIState<T>()
class ShowEmptyData<T> : UIState<T>()
class ShowData<T>(val data: T) : UIState<T>()
class ShowError<T>(val errorUIState: ErrorUIState) : UIState<T>()
}
Run Code Online (Sandbox Code Playgroud)
因此,我的viewmodel代码是:
someRequest.apply { response ->
when (response) {
is ApiResponse.Success -> {
_uiStateFlow.value = (UIState.HideLoading()) // First, hide the loading
// Do some work
_uiStateFlow.value = (UIState.ShowData(data))
}
is ApiResponse.Error -> {
_uiStateFlow.value = (UIState.ShowError(error))
}
}
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,大多数时候我的hideLoading状态不会收集,它会下降,因为成功/错误状态在 hideLoading 之后立即出现,而我的 UI 不会收集它。例如,如果我将成功/错误状态延迟设置为 100 毫秒,hideLoading将从 UI 收集。
我使用collect而不是collectLatest。
但后来我发现,当我更改设置值部分以更新 {} 时,UI 会收集所有状态。
someRequest.apply { response ->
when (response) {
is ApiResponse.Success -> {
_uiStateFlow.update { (UIState.HideLoading()) } // First, hide the loading
// Do some work
_uiStateFlow.update { (UIState.ShowData(data)) }
}
is ApiResponse.Error -> {
_uiStateFlow.update { (UIState.ShowError(error)) }
}
}
}
Run Code Online (Sandbox Code Playgroud)
那么 .value 和 update 之间有什么区别,为什么这个效果很好呢?谢谢。
PS我emit()也用过。从本质上讲,它与 .value 相同,只是一个挂起函数。
正如StateFlow 文档中所述:
对值的更新总是会被混淆。
合并意味着如果值的发布速度快于收集速度,则收集器只能获得最新的结果。这允许值始终发布到 StateFlow,而不必等待旧值被收集。
至于为什么update允许加载状态通过,我怀疑这只是因为原子更新通常需要更长的时间,因此收集器通常会赢得比赛,在这种特定情况下是在您的特定测试设备上。这不是确保收藏家获得所有中间价值的可靠解决方案。
我不明白为什么你首先需要 HideLoading 状态。您的 UI 可以在收到要显示的数据时自动隐藏加载状态。从逻辑上讲,当数据返回时,加载就完成了。
如果您确实需要此 HideLoading 状态,则应使用具有足够大值的 SharedFlowreplay以确保不会跳过它。但这也带来了其他问题,比如收藏者可能会因为重播数据而显示过时的数据。
旁注,您的密封类可能应该是一个密封接口,因为它不保存任何状态,并且其不保存状态的子级可以具有object泛型类型,Nothing因此您不必为了使用它们而不断实例化它们,并且永远不会当它们无论如何都不会持有该类型时,不必要地指定泛型类型。由于其他的是数据包装器,它们也可能是data类。像这样:
sealed interface UIState<out T> {
object ShowLoading : UIState<Nothing>
// object HideLoading : UIState<Nothing>
object ShowEmptyData : UIState<Nothing>
data class ShowData<out T>(val data: T) : UIState<T>
data class ShowError(val errorUIState: ErrorUIState) : UIState<Nothing>
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1292 次 |
| 最近记录: |