在 compose 层次 struct 中处理按钮点击的推荐方式是什么?我有一个列表,其中的项目旁边有一个编辑按钮.当用户点击按钮时,应用程序应该将该项目的视图更改为编辑器.

我想我可以将click处理函数向下传递到每个可组合对象,但这似乎不对,因为其他可组合对象只会将其传递给更深层次的对象.

对于这类案件,是否有既定的pattern人?

@Composable
fun App() {
    
    var isBrowsing = remember { mutableStateOf(true) }
    if (isBrowsing)    
        Browser() // <-- somewhere inside there is the "Edit" button
    } else {
        Editor() // <-- somewhere inside there is the "Exit" button
    }
    
}

推荐答案

请看一下this section in the documentationCompositionLocal.它的目标是使某些值在整个可合成层次中可用,而无需在每个可合成层次中显式传递这些值.

在示例中,这主要用于与主题化相关的变量.但您可以try 将其修改为使用回调函数.然而,请注意,我不确定这是否是推荐的方法,这完全是一个实验,我不知道它是否会奏效.请try 以下代码,如果有效,请返回报告:

首先,将此变量放在可组合函数之外的某个位置:

val EditorCallback = compositionLocalOf<(Boolean) -> Unit> {}

然后将此代码添加到您的可组合组件中:

@Composable
fun App() {
    
    var isBrowsing by remember { mutableStateOf(true) }

    CompositionLocalProvider(LocalElevations provides { edit -> isBrowsing = !edit}) {
        if (isBrowsing)    
            Browser()
        } else {
            Editor()
        }
    }
}

@Composable
Editor() {
    Button(onClick = { EditorCallback.current(true) }) {
        Text(text = "EDIT")
    }
}

更安全的方法是控制反转.创建一个包含布尔值的ViewModel,并将此ViewModel插入到深度嵌套的Composable以及顶级Composable中,如下所示:

@Composable
fun App(myViewModel: MyViewModel = viewModel()) {
    
    if (myViewModel.isBrowsing)    
        Browser() // <-- somewhere inside there is the "Edit" button
    } else {
        Editor() // <-- somewhere inside there is the "Exit" button
    }
    
}

@Composable
Editor(myViewModel: MyViewModel = viewModel()) {
    Button(onClick = { myViewModel.isBrowsing = true }) {
        Text(text = "EDIT")
    }
}

除了这些建议之外,我认为在Compose中传递相当多的参数是可以接受的.最后,这提高了单个可组合组件的可测试性.

Kotlin相关问答推荐

创建具有共同父类型的两种不同类型对象的列表的最有效方法是什么?

用浮点数或十进制数给出错误答案的阶乘计算

Kotlin-stdlib中的模拟扩展函数

Kotlin中是否可以混合使用推断和显式的通用类型参数?

Kotlin中用于调用常量名称的枚举类方法之间的区别

Kotlin 可空泛型

Kotlin 中的密封和内部有什么区别?

我可以在 Kotlin 中使用接口类型作为构造函数参数吗

测试协程和线程之间的差异,我在kotlin中使用线程时无法得到OOM错误

将子元素放在一个列表中

Kotlin - 当表达式返回函数类型

Kotlin - mutableMapOf() 会保留我输入的顺序

在 Kotlin 中创建 Spinner 时,如何在 Fragment 中的旋转屏幕上修复指定为非空的参数为空?

在Kotlin中为Android编写库会有开销吗?

这是 Kotlin 中的错误还是我遗漏了什么?

Kotlin-将UTC转换为当地时间

在 Kotlin 中返回函数有不那么丑陋的方法吗?

如何在 Gradle Kotlin DSL 中使用来自 gradle.properties 的插件版本?

项目不会使用 Kotlin 1.1.3 构建

Android Jetpack Compose - 图像无法zoom 到框的宽度和高度