我的应用程序的屏幕是一个带有顶部栏(CenterAlignedTopAppBar)、内容(NavHost)和底部栏(NavigationBar)的脚手架。
NavigationBar 允许在 NavHost 内切换可组合项。
NavHost 内的每个可组合项都有不同的字段和自己的 ViewModel。
CenterAlignedTopAppBar 在操作中有一个 IconButton,我想用它来保存 NavHost 内当前可组合项中的数据。
如何处理 IconButton(脚手架级别)上的单击,以通知 NavHost 内的当前 Composable 它必须通过执行自己的 ViewModel 的方法来保存其数据?
我不想将所有 ViewModel 保留在屏幕级别。
在旧的视图系统中,Fragment 可以为 Activity 菜单中的菜单项做出贡献:我可以在 Compose 中做类似的事情吗?
有什么想法吗?
我认为您提到的将密钥传递给所有可组合项然后使用
LaunchedEffect
观察变化的方法是最干净的方法。当你想触发保存时,你可以传入一个布尔值并翻转它:
@Composable
ParentWithScaffold() {
//...
var saveTrigger by remember { mutableStateOf(false) }
IconButton(onClick = { saveTrigger = !saveTrigger }) {
//...
}
}
@Composable
fun Child(saveTrigger: Boolean, /*...*/) {
LaunchedEffect(saveTrigger) {
viewModel.save()
}
}
但是,您也可以在函数内使用函数并将其传递给子可组合项,如下所示:
@Composable
fun ParentWithScaffold() {
var triggerSave by remember { mutableStateOf<() -> Unit>({}) }
// Initialize the trigger function inside the child composable
Child(setTrigger = { trigger ->
triggerSave = trigger // get the save function set from within child
})
IconButton(onClick = triggerSave) { // call save function of child
//...
}
}
@Composable
fun Child(setTrigger: (saveFunction: () -> Unit) -> Unit) {
// Expose saveFunction to the parent
val saveFunction: () -> Unit = {
// call your ViewModel save() function here
}
//...
}
您将实际的 ViewModel 保存函数设置为子级中的内部函数。然后父母就可以访问该功能。每当父进程现在调用
triggerSave()
时,子进程的保存函数就会被执行。
请注意,这与 Jetpack Compose 中使用的单向数据流 (UDF) 模式相矛盾。通常,只有数据应该向下流动,只有事件应该向上流动。这就是为什么我认为
LaunchedEffect
方法会更干净。