Functions

In Compose, you build the User Interface (UI) by creating Composable Functions. Composable Functions are simply functions that are annotated with @Composable. However, they do not operate like normal functions. Namely, you cannot call Composable Functions directly from normal functions, you can only call them from within other Composable Functions.

This is because behind the scenes, an entity called the Compose Compiler rewrites Composable Functions by adding additional parameters to them. One of the things the Compose Compiler does is add a new parameter called the Composer. Basically, this magical object tracks changes to the UI and knows when to redraw the UI. The Composer is hidden from us developers, only the Compose SDK knows how to obtain an instance of the Composer and pass it down to Composable Functions. We cannot and should not use the Composer directly, which is why we can never call Composable Functions from normal functions.

This is similar to Kotlin Coroutines. When you add suspend to any function, the Kotlin Compiler will rewrite the function and add a new parameter - Continuation - to the function. We also cannot call suspend functions directly from normal functions because of this.

You don't need to understand how the Composer works to develop apps, it just makes it easier for me to explain why they can't be called from anywhere, and when you inevitably encounter the dreaded error: @Composable invocations can only happen from the context of a @Composable function.

Let's start with a simple example: An icon and some text.

Compose Multiplatform