[英]Global Snackbar Handling Jetpack Compose
鉴于我有多个可以触发小吃店的地方,我想在我的应用程序中有一个中心位置,我可以在其中处理显示/关闭小吃店。
这是我的应用程序的结构:
我已经实现了一个包含 StateFlow 的 BaseViewModel,它应该跟踪 SnackBar 消息(所有其他 ViewModel 都继承自这个 BaseViewModel):
@HiltViewModel
open class BaseViewModel @Inject constructor() : ViewModel() {
val _snackBarMessage = MutableStateFlow("")
val snackBarMessage: StateFlow<String> = _snackBarMessage
}
为了测试 StateFlow 的更新是否被正确触发,我实现了一条消息,应该在每次登录后更新 StateFlow:
private fun setSnackBarMessage() {
_snackBarMessage.value = "A wild snackBar appeared"
}
MainContent 包含我的 Scaffold(包括scaffoldState、snackbarHost),应该对snackBarMessage 流中的变化做出反应,并在需要时显示/关闭 Snackbar:
fun MainContent(...){
val message by viewModel.snackBarMessage.collectAsState()
LaunchedEffect(message) {
if (message.isNotEmpty() Timber.d("We got a snackbar")
}
Scaffold(...){...}
}
在调试过程中,我注意到每次登录后,snackBarMessage 值都会正确更新,但 MainContent 没有得到这些更新,这反过来意味着,snackbar 永远不会显示。
MainContent 没有从 LoginComposable 获取这些更新是否有原因? 是否有可能有一个小吃店的中心实例,或者我真的需要在每个可组合中单独处理小吃店吗?
可能您的问题的原因是使用消息作为LaunchedEffect
的键,而不是同时更改消息。 在文档中,您可以阅读该类型的副作用将在密钥修改后重新启动。
如果 LaunchedEffect 用不同的 key 重构(参见下面的 Restarting Effects 部分),现有的协程将被取消,新的挂起函数将在新的协程中启动。
Compose 中的一些效果,如 LaunchedEffect、produceState 或 DisposableEffect,采用可变数量的参数和键,用于取消正在运行的效果并使用新键启动新效果。
我建议将小吃店消息包装在某种对象(不是数据类)中,其中包含包含小吃店内容的字段。
干杯
You can use this
@Composable
fun MainScreen() {
val coroutineScope = rememberCoroutineScope()
val showSnackBar: (
message: String?,
actionLabel: String,
actionPerformed: () -> Unit,
dismissed: () -> Unit
) -> Unit = { message, actionLabel, actionPerformed, dismissed ->
coroutineScope.launch {
val snackBarResult = scaffoldState.snackbarHostState.showSnackbar(
message = message.toString(),
actionLabel = actionLabel
)
when (snackBarResult) {
SnackbarResult.ActionPerformed -> actionPerformed.invoke()
SnackbarResult.Dismissed -> dismissed.invoke()
}
}
}
//Global using
showSnackBar.invoke(
"YOUR_MESSAGE",
"ACTION_LABEL",
{
//TODO ON ACTION PERFORMED
},
{
//TODO ON DISMISSED
}
)
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.