Issue
I'm following an Android Developers Codelab. I have this code fragment into a composable:
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 and onKeyBoardDone are both lambdas. This is the header of the Composable function
@Composable
fun myComposableFunction(
onUserGuessChanged: (String) -> Unit,
onKeyboardDone: () -> Unit,
modifier: Modifier = Modifier
) {
[...]
Why onValueChanged must be assigned without braces and function parenthesis, and onDone must be assigned with both?? What is the feature or difference between them?
Solution
Kotlin uses Function Types, meaning that each function has a type and you can also assign functions to variables. Once we consider functions as types, we get an idea what might be necessary to directly assign a function to onValueChange
or onDone
:
The function types of onValueChange
and the function that should be assigned to it must match.
onValueChange: (String) -> Unit
onUserGuessChanged: (String) -> Unit
// MATCH
As the types match, we can assign function A to B like we would assign one variable to another.
Similarly, the function types of onDone
and the function that should be assigned to it must match.
onDone: (KeyboardActionScope.() -> Unit)?
onKeyboardDone: () -> Unit
// DOES NOT MATCH
These types do not match out of the box. We would need a function which is an extension to the KeyboardActionScope
class.
The notation of a function type A.(B) -> C
is called a Function Literal with Receiver. We can only assign functions to such a type that either have the exact same type A.(B) -> C
or (A,B) -> C
. The onKeyboardDone
function does not fulfill this criteria.
However, if we instead wrap the function call up in another lamdba, the lambda will implicitly reflect the required type. That's why with the lambda, it suddenly works.
If you managed to declare onKeyboardDone
as a extension function of KeyboardActionScope
, you could get rid of the additional lambda.
Summary of Behavior
val onKeyboardDone: () -> Unit = { System.out.println("Hello") }
val onDone: (String.() -> Unit)? = onKeyboardDone
Compiler Error: Type mismatch: inferred type is () -> Unit but (String.() -> Unit)? was expected
val onKeyboardDone: (() -> Unit) = { System.out.println("Hello") }
val onDone: (String.() -> Unit)? = { onKeyboardDone() }
Compiler successful
Answered By - BenjyTec
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.