我有一个带有按钮的屏幕,可以执行网络调用。我需要根据网络错误在同一屏幕上显示警报对话框。
示例代码:
// AAViewModel.kt
fun fetchWeather(){
//......
//Error
}
// compose screen
@Composable
fun showWeather(){
// .....
if(dialogState.visible.value){
dialog.title
dialog.message
//Show dialog
}
}
网络调用返回错误码,所以我们必须根据错误码设置标题和错误信息。
保存dialogState的正确位置是在AAviewModel还是showWeather函数中?
根据https://developer.android.com/jetpack/compose/state-hoisting文档, UI 逻辑应该放在 compose 下,业务逻辑应该放在 ViewModel 下。 显示对话框是 UI 逻辑还是业务逻辑,我的警报的构建应该发生在 ViewModel 还是 compose 函数本身中?
在这种情况下,
AlertDialog
取决于视图模型中更新的状态,并结合标题和消息,并且它仅被观察到,并且可能被 UI 忽略。所以处理这个状态被认为是一个 business logic
并且它必须保存在视图模型中。这是一个示例实现:
首先,将当前状态调整为数据类形式的组合状态,其中包含可见性、标题和消息变量,并用
androidx.compose.runtime.Stable
注释进行标记以减少重组:
@Stable
data class AlertDialogState(
val visible: Boolean = false,
val title: String = "",
val message: String = ""
)
然后,将视图模型内的状态声明为私有
MutableStateFlow
,为 UI 声明一个公共只读 StateFlow
,以及关闭对话框的函数:
private val _alertDialogState = MutableStateFlow(AlertDialogState())
val alertDialogState = _alertDialogState.asStateFlow()
fun dismissAlertDialog() {
_alertDialogState.update { it.copy(visible = false) }
}
现在,我不知道错误处理是如何实现的,但我假设对话框的标题和消息已经声明并准备好实现,因此可以更新状态:
_alertDialogState.update {
AlertDialogState(
visible = true,
title = title,
message = errorMessage
)
}
最后,UI 可组合实现:
/// ...
val alertDialogState by viewModel.alertDialogState.collectAsState()
/// ...
if (alertDialogState.visible) {
AlertDialog(
onDismissRequest = viewModel::dismissAlertDialog,
title = { Text(text = alertDialogState.title) },
text = { Text(text = alertDialogState.message) },
confirmButton = {},
dismissButton = {
// Leave empty if you don't need a button.
TextButton(
onClick = viewModel::dismissAlertDialog,
content = { Text(text = "Dismiss") }
)
}
)
}
/// ...
查看此链接,了解有关撰写中对话框的更多信息。