Unraveling Composable: A Detailed Insight into Jetpack Compose Functions

Yasir Ameen
Rubikkube Chronicles
8 min readSep 28, 2023

Are you eager to explore Jetpack Compose in depth?🚀 Together, let’s explore the beauties of composeable functions! The “What” not “How” principle is emphasised by Jetpack Compose, revolutionising the way we build user interfaces by letting us specify what they should look like rather than how to make them. We all enjoy using cool features, but how well do you know how things work behind the scenes? A game-changer, that!

Join me as I unravel the mystery of Composable Functions. Let’s explore the fundamental ideas that give them their revolutionary status in Android programming. By doing this, we’re bringing out all of their potential and improving the way we make apps! Ready to use some Compose magic 🌟 to advance your app development journey?

“Now that we’ve set the stage, let’s dive into one of the foundational concepts of Jetpack Compose: Recomposition.”

#Recomposition:

Recomposition is a cornerstone concept in Jetpack Compose, allowing UI to automatically update when the underlying data changes. It ensures that the UI is always reflective of the latest state, making apps feel responsive and fluid. In essence, it’s all about describing ‘What’ the UI should look like, and letting Compose handle ‘How’ to get it there! 🌟

Example:

Consider a simple composable function displaying a greeting message based on a user’s name:

Recomposition Example 1.1

In this example, whenever the name parameter changes, the Greeting composable will automatically recompose, updating the displayed greeting message to match the new name. This means if the name changes from "John" to "Jane", the UI will automatically reflect this change, showcasing the power and efficiency of recomposition in Jetpack Compose! 🚀

Recomposition Example 1.2

This automatic updating or recomposition allows developers to focus more on defining the state and less on handling the UI updates, leading to more intuitive and maintainable code.

“While recomposition ensures our UI is always up-to-date, how Composables handle data and state is equally crucial. This brings us to the concept of immutability in Composables.”

#Immutable: A Simpler Perspective

In the world of Jetpack Compose, the term “immutable” holds significant importance. When we say “Composables are immutable,” we mean that they don’t retain or manage mutable state on their own. Instead, they describe a UI based on the inputs they receive at a given point in time. This immutability ensures that the UI remains predictable, consistent, and free from unexpected side effects.

What does this mean in practice?

You can’t hold a reference to a Composable function like you might with traditional objects. For instance, trying to do something like:

Immutable Example 1.1

…is not valid. Composables aren’t objects in the traditional sense; they’re more like descriptions or blueprints of a UI. When data changes, you don’t update a Composable directly. Instead, you provide it with new data, and it reinvokes itself (recomposes) to reflect those changes.

A Simple Example:

In the provided code snippet, we’re contrasting the traditional Android UI approach with the Jetpack Compose approach.

Immutable Example 1.2

Traditional Android UI Approach:

  • We first locate a TextView using findViewById.
  • Initially, we set its text to “Hello, World!”.
  • Later on, we modify the same TextView to display "Welcome to Android!".

This approach is mutable; we’re directly changing the properties of an existing UI element.

Jetpack Compose Approach:

  • We define a Composable function, DisplayMessage, which takes a message parameter.
  • This function describes a UI element, a Text, which displays the provided message.
  • To display “Hello, World!”, we call DisplayMessage with that string.
  • If we want to display a different message, we don’t modify the existing UI. Instead, we call DisplayMessage again with the new message, "Welcome to Jetpack Compose!".

In Compose, we’re not modifying UI elements directly. We’re describing what the UI should look like based on the data (in this case, the message). This approach is more declarative and aligns with the principle of immutability in Jetpack Compose.

“Understanding the immutable nature of Composables is just the beginning. Next, we’ll explore the unique ways in which Composables execute, setting them apart from traditional UI frameworks.”

#Execution Order and Efficient Skipping:

In Jetpack Compose, the way Composables execute and update is fundamentally different from traditional UI frameworks. Two key concepts underpin this behavior: the flexible execution order of Composables and their ability to efficiently skip unnecessary updates.

Flexible Execution Order:

Composables are designed to be order-agnostic. This means that the sequence in which they are defined doesn’t strictly dictate the order in which they execute. For instance, even if you define Header(), Content(), and Footer() in that sequence, Compose might choose to execute them in a different order based on optimization needs.

Efficient Skipping:

Coupled with the flexible execution order is Compose’s ability to skip unnecessary recompositions. If only a specific part of the data changes, Compose can selectively re-invoke only the affected Composables, leaving the others untouched. This selective recomposition ensures that the UI remains responsive, as only the necessary parts are redrawn.

A Unified Example:

Consider a UI layout:

Execution Order and Efficient Skipping 1.1

In traditional UI frameworks, a change in the content might necessitate a complete redraw of the entire UI. However, with Jetpack Compose, if only the isWelcome flag changes, Compose might choose to re-invoke just the Content Composable, efficiently skipping Header and Footer.

“With the flexibility in execution comes a responsibility: managing side effects. Let’s delve into why side-effect free design is paramount in Jetpack Compose.”

#Side Effects Free Composables

Jetpack Compose revolutionizes how we think about UI development, emphasizing a declarative approach. A crucial aspect of this paradigm is ensuring Composables remain side-effect free. But what does this mean, and why is it essential?

Side Effects: A Brief Overview

In programming, a side effect refers to any operation that modifies state outside its local environment. For UI, this could mean altering global variables or triggering external actions. While side effects are common in procedural programming, they can introduce unpredictability and inconsistencies in a declarative framework like Compose.

The Don’ts: Modifying Global State

Composable Side Effects Example 1.1

In the BadItemList example, the Composable modifies a global list every time it's invoked. This approach is problematic:

  1. Unpredictability: The behavior of the Composable becomes dependent on external factors.
  2. Recomposition Challenges: Composables can be re-invoked for various reasons. Modifying global state during these recompositions can lead to unexpected behaviors.
  3. Concurrency Issues: With potential parallel execution in Compose, direct global state modifications risk race conditions.

The Do’s: Embracing Local State Management

Composable Side Effects Example 1.2

The GoodItemList example showcases the recommended approach. By using remember and mutableStateListOf, the list's state is managed locally within the Composable. This design ensures:

  1. Consistency: The Composable’s behavior remains consistent across recompositions.
  2. Safety: Local state management avoids potential concurrency issues.
  3. Clarity: By isolating state within the Composable, the code becomes easier to read and maintain.

In Jetpack Compose, the key to crafting reliable and efficient UIs lies in understanding and embracing the side-effect free nature of Composables. By managing state locally and avoiding global modifications, developers can harness the full power and elegance of this modern UI toolkit.

“Having grasped the importance of side-effect free design, it’s time to dive deeper into the dynamics of Composables. Specifically, how they benefit from parallelism and their inherent reactivity.”

#Parallelism & Reactivity in Composables

Jetpack Compose, Android’s modern UI toolkit, introduces a fresh approach to UI development, emphasizing both parallel execution and reactive recomposition. These two principles, while distinct, collectively shape the efficiency and responsiveness of Composables.

Embracing Parallel Execution:

At its core, Jetpack Compose is designed to potentially run Composables concurrently. This parallelism is possible because Composables, being side-effect free, can be executed without the risk of race conditions or data inconsistencies. As a result, different segments of the UI can be updated simultaneously, leading to smoother and more efficient UI updates.

The Reactive Nature of Recomposition:

Beyond parallelism, Composables are inherently reactive. When the data they depend on undergoes changes, Composables automatically recompose, ensuring the UI is always in sync with the latest data. This reactivity means that Composables can, and often do, recompose frequently, especially in dynamic UI scenarios.

What This Means for Developers:

  1. Optimized Performance: The potential for parallel execution ensures that UI updates are swift, taking full advantage of multi-core processors.
  2. Responsiveness: The reactive nature guarantees that the UI is always up-to-date, reflecting real-time data changes.
  3. Design Caution: Given the frequent and potentially parallel recomposition, it’s imperative for Composables to remain side-effect free, ensuring predictable behavior.

Illustrative Example:

Consider a real-time stock market app:

Parallelism & Reactivity in Composables 1.1

In this app, as stock data updates pour in, different parts of the dashboard might recompose concurrently and frequently, highlighting the importance of both parallelism and reactivity in Compose.

#Conclusion & Summary

In our journey through Jetpack Compose, we’ve uncovered the transformative principles that make it a game-changer in Android UI development. From the reactive nature of recomposition to the immutable essence of Composables, we’ve seen how this modern toolkit reshapes our approach to crafting user interfaces.

Jetpack Compose’s emphasis on describing “What” rather than “How” not only simplifies UI development but also makes it more intuitive and efficient. By embracing parallelism and ensuring side-effect free design, Composables offer both speed and reliability, a combination every developer dreams of.

As we wrap up, it’s essential to remember that the true power of Jetpack Compose lies in understanding its core concepts. By doing so, we’re not just using a new toolkit; we’re adopting a paradigm shift, one that promises a brighter and more efficient future for Android development.

To all developers embarking on this Compose journey, here’s to crafting UIs that are not only beautiful but also smart, responsive, and efficient. Happy coding! 🚀

--

--

Yasir Ameen
Rubikkube Chronicles

CEO at Rubikkube, specializing in impactful mobile apps. Award-winner with a background in both iOS and Android. Transforming innovative ideas into market hits!