我正在关注一个Android开发者Codelab.我将此代码片段转换为可组合的:

            OutlinedTextField(
                value = userGuess,
                singleLine = true,
                shape = shapes.large,
                modifier = Modifier.fillMaxWidth(),
                colors = TextFieldDefaults.colors(
                    focusedContainerColor = colorScheme.surface,
                    unfocusedContainerColor = colorScheme.surface,
                    disabledContainerColor = colorScheme.surface,
                ),
                onValueChange =  onUserGuessChanged ,
                label = { Text(stringResource(R.string.enter_your_word)) },
                isError = false,
                keyboardOptions = KeyboardOptions.Default.copy(
                    imeAction = ImeAction.Done
                ),
                keyboardActions = KeyboardActions(
                    onDone = { onKeyboardDone() }
                )
            )

OnUserGuessChanged和onKeyBoardDone都是lambdas.这是Composable函数的头

@Composable
fun myComposableFunction(
    onUserGuessChanged: (String) -> Unit,
    onKeyboardDone: () -> Unit,
    modifier: Modifier = Modifier
) { 
[...]

为什么onValueChanged必须不带大括号和函数括号赋值,而onDone必须同时赋值??它们之间有什么特点或区别?

推荐答案

Kotlin使用Function Types,这意味着每个函数都有一个类型,您还可以将函数赋给变量.一旦我们将函数视为类型,我们就知道了将函数直接赋给onValueChangeonDone可能需要什么:

onValueChange中的function types和应该分配给它的功能must match.

onValueChange:      (String) -> Unit
onUserGuessChanged: (String) -> Unit
// MATCH

当类型匹配时,我们可以将函数A赋给B,就像将一个变量赋给另一个变量一样.

类似地,onDone中的function types和应该分配给它的功能must match.

onDone:         (KeyboardActionScope.() -> Unit)?
onKeyboardDone: () -> Unit
// DOES NOT MATCH

这些类型开箱即用不匹配.我们需要一个KeyboardActionScope类的扩展函数.

函数类型A.(B) -> C的表示法称为Function Literal with Receiver.我们只能将函数分配给具有完全相同的A.(B) -> C(A,B) -> C类型的类型.onKeyboardDone函数不符合此标准.

但是,如果我们将函数调用包装在另一个lamdba中,则lambda将为implicitly reflect the required type.这就是为什么在Lambda上,它突然起作用了.

如果您成功地将onKeyboardDone声明为KeyboardActionScope的扩展函数,则可以go 掉额外的lambda.

Kotlin相关问答推荐

直接从SON解析NonEmptyList

Compose:LaunchedEffect在密钥更改后不会重新启动

Kotlin协程挂起继续线程

可选的.在kotlin中不使用泛型参数

用Quarkus和Reactor重写异步过滤器中的数据流

有没有什么方法或算法可以在没有存储的情况下生成唯一的随机数?

为什么多线程不会使执行更快

如何将 `throw` 放置在辅助函数中但仍然具有空安全性?

Jetpack compose 可滚动表格

添加 Kapt 插件后 - 执行 org.jetbrains.kotlin.gradle.internal.KaptExecution 时发生故障

将 jetpack compose 添加到现有元素

如何在 android jetpack compose 中相互重叠列表项?

Kotlin内联扩展属性

无法在Kotlin中使用argb color int值?

Kotlin lambda 语法混淆

在android的默认浏览器 Select 列表中添加我的浏览器?

Dagger +Kotlin 不注入

Kotlin-将UTC转换为当地时间

在多平台子元素中使用kapt

在 Kotlin 中声明 Byte 会出现编译时错误The integer literal does not conform to the expected type Byte