代码A来自这里的官方示例项目。
InterestsViewModel
定义uiState
为StateFlow
,collectAsState()
在可组合函数rememberTabContent
中将其转换为State<T>
。
我很奇怪为什么作者没有在InterestsViewModel
中直接将uiState
定义为State<T>
,所以我写了代码b
代码B可以编译,也可以运行,但是屏幕上什么都不显示,代码B怎么了?
代码
data class InterestsUiState(
val topics: List<InterestSection> = emptyList(),
val people: List<String> = emptyList(),
val publications: List<String> = emptyList(),
val loading: Boolean = false,
)
class InterestsViewModel(
private val interestsRepository: InterestsRepository
) : ViewModel() {
// UI state exposed to the UI
private val _uiState = MutableStateFlow(InterestsUiState(loading = true))
val uiState: StateFlow<InterestsUiState> = _uiState.asStateFlow()
...
init {
refreshAll()
}
private fun refreshAll() {
_uiState.update { it.copy(loading = true) }
viewModelScope.launch {
...
// Wait for all requests to finish
val topics = topicsDeferred.await().successOr(emptyList())
val people = peopleDeferred.await().successOr(emptyList())
val publications = publicationsDeferred.await().successOr(emptyList())
_uiState.update {
it.copy(
loading = false,
topics = topics,
people = people,
publications = publications
)
}
}
}
}
@Composable
fun rememberTabContent(interestsViewModel: InterestsViewModel): List<TabContent> {
// UiState of the InterestsScreen
val uiState by interestsViewModel.uiState.collectAsState()
...
return listOf(topicsSection, peopleSection, publicationSection)
}
@Composable
fun InterestsRoute(
interestsViewModel: InterestsViewModel,
isExpandedScreen: Boolean,
openDrawer: () -> Unit,
scaffoldState: ScaffoldState = rememberScaffoldState()
) {
val tabContent = rememberTabContent(interestsViewModel)
val (currentSection, updateSection) = rememberSaveable {
mutableStateOf(tabContent.first().section)
}
InterestsScreen(
tabContent = tabContent,
currentSection = currentSection,
isExpandedScreen = isExpandedScreen,
onTabChange = updateSection,
openDrawer = openDrawer,
scaffoldState = scaffoldState
)
}
代码B
data class InterestsUiState(
val topics: List<InterestSection> = emptyList(),
val people: List<String> = emptyList(),
val publications: List<String> = emptyList(),
var loading: Boolean = false,
)
class InterestsViewModel(
private val interestsRepository: InterestsRepository
) : ViewModel() {
// UI state exposed to the UI
private var _uiState by mutableStateOf (InterestsUiState(loading = true))
val uiState: InterestsUiState = _uiState
...
init {
refreshAll()
}
private fun refreshAll() {
_uiState.loading = true
viewModelScope.launch {
...
_uiState = _uiState.copy(
loading = false,
topics = topics,
people = people,
publications = publications
)
}
}
}
@Composable
fun rememberTabContent(interestsViewModel: InterestsViewModel): List<TabContent> {
// UiState of the InterestsScreen
val uiState = interestsViewModel.uiState
...
return listOf(topicsSection, peopleSection, publicationSection)
}
您在可组合val uiState: InterestsUiState = _uiState
中使用的uiState
不是状态,因此不响应更改。它只是一个普通的InterestsUiState
,用_uiState
的当前值初始化。要使其工作,您可以简单地公开_uiState
的getter。
var uiState by mutableStateOf (InterestsUiState(loading = true))
private set
现在这个uiState
只能从ViewModel内部修改,当你在Composable中使用它时,只要uiState
的值改变,就会发生重组。