在 Compose 中,如何单击屏幕级别的 IconButton 来执行嵌套级别的 Composable 拥有的 ViewModel 方法?

问题描述 投票:0回答:1

我的应用程序的屏幕是一个带有顶部栏(CenterAlignedTopAppBar)、内容(NavHost)和底部栏(NavigationBar)的脚手架。
NavigationBar 允许在 NavHost 内切换可组合项。
NavHost 内的每个可组合项都有不同的字段和自己的 ViewModel。
CenterAlignedTopAppBar 在操作中有一个 IconButton,我想用它来保存 NavHost 内当前可组合项中的数据。
如何处理 IconButton(脚手架级别)上的单击,以通知 NavHost 内的当前 Composable 它必须通过执行自己的 ViewModel 的方法来保存其数据?
我不想将所有 ViewModel 保留在屏幕级别。
在旧的视图系统中,Fragment 可以为 Activity 菜单中的菜单项做出贡献:我可以在 Compose 中做类似的事情吗?
有什么想法吗?

android navigation android-jetpack-compose
1个回答
0
投票

我认为您提到的将密钥传递给所有可组合项然后使用

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
方法会更干净。

© www.soinside.com 2019 - 2024. All rights reserved.