0

What does @Composable() (() -> Unit)? do? I see it defined as a parameter to OutlinedTextField in Jetpack Compose. I know @Composable() -> Unit means you pass a composable that takes no parameter, but this one is strange and it does not even have a return type.

ntos
  • 189
  • 10

2 Answers2

0

() -> Unit is a type, just like Int for example. It is a function that takes no arguments and returns Unit. If you want to make a type nullable, you append ? to the type, so Int becomes Int?.

With functional types, you can do () -> Unit?, but that is a nonnull function that returns Unit?. If you want the function itself to be nullable, you have to add parentheses: (() -> Unit)?.

This is what happens in OutlinedTextField. The actual declaration looks like this:

@Composable
fun OutlinedTextField(
    placeholder: @Composable (() -> Unit)? = null,
    ...

)

They simply wanted to make the placeholder argument nullable

Jan Bína
  • 3,447
  • 14
  • 16
0

Some Composables take nullable lambdas for slots as in OutlinedTextField as label: @Composable (() -> Unit)? = null to give option for any slots that are not mandatory to be available while some others like Scaffold uses topBar: @Composable () -> Unit = {} lambdas with empty default values in case you don't want to pass some of the slots defined in Composable.

Both notions can be used when you create a Composable with optional slots.

And @Composable() (() -> Unit) it's a function type and generally used in other Composable functions for slot api.

@Composable annotation resembles lets you access to other @Composale ui functions such as Row, Column, Box, etc., or non-ui functions such as remember, LaunchEffect, SideEffect, DisposableEffect or composer object. It resembles suspend function type which lets you call other suspending functions.

// function type
fun MyFun(myParam: suspend () -> Unit) { … }

// function type
fun MyFun(myParam: @Composable () -> Unit) { … }

https://stackoverflow.com/a/73261429/5457853

And a Composable function that is not inline and returns unit is considered as scope that's why Composable ui functions return unit. A scope is where recomposition.

https://dev.to/zachklipp/scoped-recomposition-jetpack-compose-what-happens-when-state-changes-l78

For every non-inline composable function that returns Unit, the Compose compiler generates code that wraps the function’s body in a recompose scope. When a recompose scope is invalidated, the compose runtime will ensure the (entire) function body gets recomposed (reexecuted) before the next frame. Functions are a natural delimiter for re-executable chunks of code, because they already have well-defined entry and exit points.

Foo’s body, Button’s body, the content lambda we pass to Button, Text’s body, all get their own recompose scopes.

Thracian
  • 43,021
  • 16
  • 133
  • 222
  • I would like to know why they added the extra brackets `( )` after `Compose`: @Composable`()` (() -> Unit). Are they optional? I mean `@Composable() (() -> Unit) == @Composable () -> Unit`, isn't it? – ntos Aug 30 '23 at 22:21
  • Yes, they both mean same thing but In TextField they actually use nullable lambdas which are placeholder: @Composable (() -> Unit)? = null, and some composables use `@Composable () -> Unit = {}` which both are for optional slots or content Composables that are not supposed to be available in every implementation. You can refer https://stackoverflow.com/q/38784939/5457853, https://stackoverflow.com/questions/51733552/how-do-i-idiomatically-call-a-nullable-lambda-in-kotlin/51734014#51734014. And in some Composables they use – Thracian Aug 30 '23 at 22:57
  • Thank you Thracian. You have been very helpful. – ntos Aug 30 '23 at 23:15