No momento, você está visualizando Thinking in Compose

Thinking in Compose

Jetpack Compose is a modern declarative UI Toolkit for Android. Compose makes it easier to write and maintain your app UI by providing a declarative API that allows you to render your app UI without imperatively mutating frontend views.

Intuitive: Thinking in Compose

The declarative programming paradigm

Over the last several years, the entire industry has started shifting to a declarative UI model, which greatly simplifies the engineering associated with building and updating user interfaces. The technique works by conceptually regenerating the entire screen from scratch, then applying only the necessary changes. This approach avoids the complexity of manually updating a stateful view hierarchy. Compose is a declarative UI framework.

One challenge with regenerating the entire screen is that it is potentially expensive, in terms of time, computing power, and battery usage. To mitigate this cost, Compose intelligently chooses which parts of the UI need to be redrawn at any given time. This does have some implications for how you design your UI components. We will discuss it later in Recomposition.

A simple composable function

Using Compose, you can build your user interface by defining a set of composable functions that take in data and emit UI elements. A simple example is a Greeting widget, which takes in a String and emits a Text widget which displays a greeting message.

A simple composable function that is passed data and uses it to render a text widget on the screen.

A few noteworthy things about this function:

  • The function is annotated with the @Composable annotation. All Composable functions must have this annotation; this annotation informs the Compose compiler that this function is intended to convert data into UI.
  • The function takes in data. Composable functions can accept parameters, which allow the app logic to describe the UI. In this case, our widget accepts a String so it can greet the user by name.
  • The function displays text in the UI. It does so by calling the Text() composable function, which actually creates the text UI element. Composable functions emit UI hierarchy by calling other composable functions.
  • The function doesn’t return anything. Compose functions that emit UI do not need to return anything, because they describe the desired screen state instead of constructing UI widgets.
  • The function behaves the same way when called multiple times with the same argument, and it does not use other values such as global variables or calls to random().
  • The function describes the UI without any side-effects, such as modifying properties or global variables.

In general, all composable functions should be written with these properties, for reasons discussed in Recomposition.

The declarative paradigm shift

In Compose’s declarative approach, widgets are relatively stateless and don’t expose setter or getter functions. In fact, widgets are not exposed as objects. You update the UI by calling the same composable function with different arguments. This makes it easy to provide state to architectural patterns such as a ViewModel, as we will describe in the Guide to app architecture. Then, your composables are responsible for transforming the current application state into a UI every time the observable data updates.

The app logic provides data to the top-level composable function. That function uses the data to describe the UI by calling other composables, and passes the appropriate data to those composables, and on down the hierarchy.

When the user interacts with the UI, the UI raises events such as onClick. Those events should notify the app logic, which can then change the app’s state. When the state changes, the composable functions are called again with the new data. This causes the UI elements to be redrawn–this process is called recomposition.

The user interacted with a UI element, causing an event to be triggered. The app logic responds to the event, then the composable functions are automatically called again with new parameters, if necessary.

Dynamic content

Because composable functions are written in Kotlin instead of XML, they can be as dynamic as any other Kotlin code. For example, suppose you want to build a UI that greets a list of users:

@Composable
fun Greeting(names: List<String>) {
    for (name in names) {
        Text("Hello $name")
    }
}

This function takes in a list of names and generates a greeting for each user. Composable functions can be quite sophisticated. You can use if statements to decide if you want to show a particular UI element. You can use loops. You can call helper functions. You have the full flexibility of the underlying language. This power and flexibility is one of the key advantages of Jetpack Compose.