我正在阅读Android UI 层速成课程,其中建议通过密封类对复杂的 UI 状态进行建模,例如像这样:
我会以
的形式向 UI (Compose) 公开这样的状态private val _uiState = MutableStateFlow<HomeUiState>(HomeUiState.NoPosts()) // flow of type HomeUiState
val uiState = _uiState.asStateFlow()
现在,如果我从 UI 触发业务逻辑,例如
// in the UI
when (uiState) {
is HasPosts -> { // smart cast from interface type to concrete data class HomeUiState.HasPosts
// Action triggered e.g. by a button
viewModel.refreshPosts()
}
}
似乎我总是必须在 ViewModel 中进行类型转换,然后才能访问触发函数的 UiState 特定的成员。
// ViewModel
fun refreshPosts() {
if(uiState.value is HomeUiState.HasPosts) {
// here I can access HasPosts's specfic members like postsFeed
uiState.postsFeed.refresh()
}
}
我无法想象我必须在每个 ViewModel 函数中进行类型转换才能访问 UiState 的属性。例如。想想像
UiState.Loading
和 UiState.Success
这样的 UiState:ViewModel 中的大多数函数都会在 UiState.Success
状态上运行,仅仅因为我有另一个 UiState,我需要在任何地方进行转换?
我肯定错过了一些东西?!
只有观察者中的
when
块知道 uiState.value
属于特定类型。当您调用 viewModel.refreshPosts()
时,基础值可能已更改,因此您需要再次确认类型。
相反,假设这是要更改某些“刷新”按钮的状态,请使用观察者块来更新您的单击处理,并将强类型值传递给您的
ViewModel
方法:
fun refreshPosts(feed: PostsFeed) {
feed.refresh()
}
然后你的观察者可以直接传入智能铸造的对象:
when (uiState) {
is HasPosts ->
refreshButton.setOnClickListener {
viewModel.refreshPosts(uiState.postsFeed)
}
}
我假设这是一个简化的示例,但在您的情况下,您可能根本不需要
refreshPosts
方法,而应该直接调用 uiState.postsFeed.refresh()
。