android - 如何正确使用 StateFlow 和 Jetpack compose?
问题描述
我正在 ViewModel 中进行 API 调用,并在可组合物中观察它,如下所示:
class FancyViewModel(): ViewModel(){
private val _someUIState =
MutableStateFlow<FancyWrapper>(FancyWrapper.Nothing)
val someUIState: StateFlow<FancyWrapper> =
_someUIState
fun attemptAPICall() = viewModelScope.launch {
_someUIState.value = FancyWrapper.Loading
when(val res = doAPICall()){
is APIWrapper.Success -> _someUIState.value = FancyWrapper.Loading(res.vaue.data)
is APIWrapper.Error -> _someUIState.value = FancyWrapper.Error("Error!")
}
}
}
在可组合中,我正在听这样的“someUIState”:
@Composable
fun FancyUI(viewModel: FancyViewModel){
val showProgress by remember {
mutableStateOf(false)
}
val openDialog = remember { mutableStateOf(false) }
val someUIState =
viewModel.someUIState.collectAsState()
when(val res = someUIState.value){
is FancyWrapper.Loading-> showProgress = true
is FancyWrapper.Success-> {
showProgress = false
if(res.value.error)
openDialog.value = true
else
navController.navigate(Screen.OtherScreen.route)
}
is FancyWrapper.Error-> showProgress = false
}
if (openDialog.value){
AlertDialog(
..
)
}
Scaffold(
topBar = {
Button(onClick={viewModel.attemptAPICall()}){
if(showProgress)
CircularProgressIndicator()
else
Text("Click")
}
}
){
SomeUI()
}
}
我面临的问题是 FancyUI 可组合中 someUIState 的“何时”块代码在可组合重组期间被多次触发,即使没有单击 Scaffold 中的按钮(例如:当 AlertDialog 出现时)。我在哪里做错了?在 Composable 中使用 StateFlow 观察数据的正确更好方法是什么?
解决方案
如果您只想处理每个someUIState
值一次,则应将其放在 a 中LaunchedEffect
并作为键传递someUIState
,以便在它更改时重新触发块。
val someUIState by viewModel.someUIState.collectAsState()
LaunchedEffect(someUiState) {
when(someUiState) {
// Same as in the question
}
}
或者,您可以只在LaunchedEffect
.
LaunchedEffect(Unit) {
viewModel.someUIState.collect { uiState ->
when(uiState) {
// Same as in the question
}
}
}
推荐阅读
- arrays - 如何在角度 4 中创建 json 对象并使用键/值对推送数组
- json - lJSON-LD 语法错误:需要值、对象或数组
- javascript - 使用文件夹内的文件名填写 URL
- powershell - PowerShell 中的“$myvariable =”和 Set-Variable 有什么不同?
- x86 - “.com”文件和“.bin”文件有什么区别?
- java - 如何在手机视图中将动画右用于侧边栏菜单?
- java - Play Framework 2.7 授权获取用户
- angular - 使用 Angular + 材料在 IE 11 中的输入类型 =“数字”中支持“,”
- virtualbox - minikube 启动失败 - 没有这样的用户
- sql - 如何选择不重复的日期间隔?