[英]Performing single shot operations using SharedFlow without casting to needed value
I have the following SharedFlow in my viewmodel -我的视图模型中有以下 SharedFlow -
class HeroesViewModel(private val heroesRepositoryImpl: HeroesRepositoryImpl) : ViewModel() {
private val _uiState = MutableStateFlow(UiState())
val uiState = _uiState.asStateFlow()
private val _uiAction = MutableSharedFlow<UiAction>()
val uiAction = _uiAction.asSharedFlow()
sealed class UiAction {
data class NavigateToHeroesDetails(val heroModel: HeroModel) : UiAction()
}
And I implement the observing of it in my Composable screen -我在我的可组合屏幕中实现了对它的观察 -
fun DashboardScreen(
navigator: DestinationsNavigator,
viewModel: HeroesViewModel = get()
) {
val uiState by viewModel.uiState.collectAsState()
val uiAction by viewModel.uiAction.collectAsState(initial = null)
when (uiAction) {
is HeroesViewModel.UiAction.NavigateToHeroesDetails -> {
navigator.navigate(HeroDetailsScreenDestination(uiAction.heroModel)) // Here is where I get the compiler error
}
null -> Unit
}
When trying to use the information from the action, the compiler gives me the following error -尝试使用操作中的信息时,编译器给我以下错误 -
Smart cast to 'HeroesViewModel.UiAction.NavigateToHeroesDetails' is impossible, because 'uiAction' is a property that has open or custom getter
What would be the correct way verify that the variable is indeed of the type I want?验证变量确实是我想要的类型的正确方法是什么?
If you want to keep the by
delegate then a simple way is to assign to a val
inside the when
expression如果您想保留
by
委托,那么一种简单的方法是在when
表达式中分配一个val
val uiAction by viewModel.uiAction.collectAsState(initial = null)
@Suppress("UnnecessaryVariable")
when (val action = uiAction) {
is HeroesViewModel.UiAction.NavigateToHeroesDetails -> {
HeroDetailsScreenDestination(action.heroModel)
}
null -> Unit
}
There are other ways as well还有其他方法
with(uiAction) { when (this) {... } }
uiAction.run { when (this) {... } }
uiAction.let { when (it) {... } }
If you don't need the by
delegate, then you can do如果您不需要代理
by
,那么您可以这样做
val uiAction = viewModel.uiAction.collectAsState(initial = null)
when (val action = uiAction.value) {
is HeroesViewModel.UiAction.NavigateToHeroesDetails -> {
HeroDetailsScreenDestination(action.heroModel)
}
null -> Unit
}
And if you just need read-only access in the current scope, then you can simplify it to如果您只需要当前 scope 中的只读访问权限,那么您可以将其简化为
val uiAction = viewModel.uiAction.collectAsState(initial = null).value
when (uiAction) {
is HeroesViewModel.UiAction.NavigateToHeroesDetails -> {
HeroDetailsScreenDestination(uiAction.heroModel)
}
null -> Unit
}
So the answer that helped me to achieve my goal was to initiate a coroutine using the LaunchedEffect
block, and inside it collecting the latest UI action -因此,帮助我实现目标的答案是使用
LaunchedEffect
块启动协程,并在其中收集最新的 UI 动作 -
LaunchedEffect(key1 = "") {
viewModel.uiAction.collect { uiAction ->
when (uiAction) {
is HeroesViewModel.UiAction.NavigateToHeroesDetails -> {
navigator.navigate(HeroDetailsScreenDestination(uiAction.heroModel))
}
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.