Quick reference guide for Compose Recomposition

Mauricio Ponce
GlobalLogic LatAm
Published in
4 min readJul 23, 2024

Render a frame

Like most other UI toolkits, Compose renders a frame through several distinct phases and has three main phases:

The three phases of a frame in Compose.

Three phases of a frame

Let’s diving into each of these phases:

1. Composition

In the composition phase, the Compose runtime executes composable functions and constructs a hierarchy of composables, representing the current state of the UI. This hierarchy is represented as a tree structure that defines your UI and consists of layout nodes containing all the information needed for the subsequent phases.

Each composable function in the code maps to a single layout node in the UI tree.

Input: Composable functions.

Output: Tree structure with layout nodes representing the UI.

Key functions:

remember: Retains state across recompositions but does not save state across configuration changes (API doc).

rememberSaveable: Retains state across recompositions and saves state across configuration changes (API doc).

2. Layout

In the layout phase, Compose uses the UI tree as input. The collection of layout nodes contains all the information needed to decide each node’s size and location in 2D space.

Input: UI Tree from previous compose phase.

Output: Measurement and position of each node (UI elements)

Key functions:

Modifier.layout: Customizes how a composable is measured and laid out, allowing for custom measurement, custom placement, and advanced layout scenarios.

Modifier.padding: Adds space around an element.

Modifier API doc

3. Draw

In the drawing phase, the tree is traversed again from top to bottom, and each node draws itself on the screen. This phase involves rendering visual aspects, such as shapes, text, images, and other elements, onto a canvas using APIs like Canvas and DrawScope.

Input: UI tree with all necessary information for drawing.

Output: UI elements rendered onto the screen.

Key functions:

Modifier.drawWithContent: Allows customization of the drawing order of a composable and its drawing commands.

Modifier.drawBehind: A convenient wrapper around drawWithContent that draws behind the composable’s content.

How do these three phases interact?

In a broader context, the purpose of these three phases is to transform composables (data) into a User Interface (UI).

Recomposition

Recomposition occurs when the state changes due to an event. The three phases are re-executed to update the UI accordingly.

You call the composable function again with new data and the function is recomposed–the widgets emitted by the function are redrawn, if necessary, with new data.

Background

The execution order of these three phases is ruled by the unidirectional data flow design pattern where state flows down and events flow up.

Unidirectional Data Flow pattern brief.

Performance

You can safely assume that these three phases happen virtually for every frame, but for the sake of performance, Compose avoids repeating work that would compute the same results from the same inputs in all of these phases. Compose skips running a composable function if it can reuse a former result, and Compose UI doesn’t re-layout or re-draw the entire tree if it doesn’t have to. Compose performs only the minimum amount of work required to update the UI. This optimization is possible because Compose tracks state reads within the different phases.

Jetpack Compose phases | Android Developers

Android Studio include a Layout inspector that can be used to explore the view layout hierarchy and it can be used to check how often a composable is recomposed or skipped, which can help identify issues with your app.

Key Learnings

  • Recomposition involves calling a composable function with new data and redrawing widgets using a three-phase process: composition, layout, and drawing.
  • Understand UDF pattern is a key to build better composables.

Wormholes

Last but not least

This content is based on the official Android documentation. All diagrams and images are derived from this documentation and are created to serve as easy-to-access reminders. Suggestions for improvements are welcome and encouraged.

By Mauricio Ponce Oyarzún, Associate Specialist Engineer at GlobalLogic.

References

--

--