JetPack Compose Lambda understanding

413 views Asked by At

This is the imagei am new to jetpack Compose. I have opened my first jetpack compose project today. I am little confuse regarding the initial syntax. i have highlighted the curly brackets. My question is are the lambdas inside lambdas? i have went through kotlin tutorial and haven't found any such structure. A little explanation with some example will be very helpful. Thanks in advance

I am just trying to understand the mentioned code structure

2

There are 2 answers

2
Atul Sharma On

are the lambdas inside lambdas?

Yes, these are nested lambdas. Before you get your answer you should familiar with higher-order function that is the functions which takes another function as paramenter or as return type are called higher-order functions.

A higher-order function is a function that takes functions as parameters, or returns a function.

If trailing parameter (last one) of higher-order function is itself a function then you can pass the function in the form of lambda.

For example: Here is the listener for the motion done on any view.

fun attachMotionListener(
    onDragged: () -> Unit,
    onClicked: () -> Unit
)

Now you can call the function in two ways:

// Here we have passed the paramenters without using any special syntax
attachMotionListener(
    onDragged = { /* do something when dragged */ }
    onClicked = { /* do something when clicked */ }
)

// Here we use the trailing lambda syntax
attachMotionListener(
    onDragged = { /* do something when dragged */ }
) {
    /* do something when clicked */
}

By using this technique the composable functions are defined as the last parameter of setContent is of function type that's why we use trailing-lambda using curly-brackets. As you can see in the following code of button from material-3 docs:

@Composable
fun Button(
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    shape: Shape = ButtonDefaults.shape,
    colors: ButtonColors = ButtonDefaults.buttonColors(),
    elevation: ButtonElevation? = ButtonDefaults.buttonElevation(),
    border: BorderStroke? = null,
    contentPadding: PaddingValues = ButtonDefaults.ContentPadding,
    interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
    content: @Composable RowScope.() -> Unit
)

Here you can see that the onClick is not trailing so we can't use trailing-lambda syntax here but the trailing parameter is also of type function here we can use the syntax and you also might have noticed it:

Button(onClick = { /*TODO*/ }) {
    Text("Hello World!")
}

You might have noticed @Composable annotation its telling the compiler that this is composable function and any Composable component can be called in the another function that's why the content parameter in Button has also this annotation used and hence we can call other composable within the scope of this function.

0
andylee On

Each basic composables like Surface and Theme are just functions(not objects) that takes another composabe lambda as the last argument.

Check the code below for definition of surface

@Composable
@NonRestartableComposable
fun Surface(
    modifier: Modifier = Modifier,
    shape: Shape = RectangleShape,
    color: Color = MaterialTheme.colorScheme.surface,
    contentColor: Color = contentColorFor(color),
    tonalElevation: Dp = 0.dp,
    shadowElevation: Dp = 0.dp,
    border: BorderStroke? = null,
    content: @Composable () -> Unit
) {

If the last argument after default parameters is a lambda, you can pass it either as a named argument or outside the parentheses . So they are just nested lambdas used as last arguments.