Exploring the Art of Recomposition in Jetpack Compose: Tips and Tricks

Exploring the Art of Recomposition in Jetpack Compose: Tips and Tricks

ยท

4 min read

In this article, we will explore recomposition and how it can be used in Android Jetpack Compose.

In Android programming, we currently have two types of ways of programming User Interfaces which are the imperative way and the declarative way of programming User Interfaces in android. And just to have a brief explanation of the difference between these two.

Imperative User Interface programming necessitates specifying the individual steps to construct and modify the user interface, while declarative User interface programming entails defining the intended final appearance of the UI and allowing the framework to take care of the creation and updates. Below we demonstrate the difference between these two ways of User interface programming in Android.

The imperative way of programming UI in Android

val textView = TextView(context)
textView.text = "Hello, World!"
textView.textSize = 18f
textView.setTextColor(Color.BLACK)
textView.setBackgroundColor(Color.WHITE)

val layoutParams = RelativeLayout.LayoutParams(
    RelativeLayout.LayoutParams.WRAP_CONTENT,
    RelativeLayout.LayoutParams.WRAP_CONTENT
)
layoutParams.addRule(RelativeLayout.CENTER_IN_PARENT)

textView.layoutParams = layoutParams

// Add the view to the parent layout
parentLayout.addView(textView)

The code snippet above showcases imperative programming to define the UI step by step. A TextView object is created, and its properties such as text, text size, and colour are set. Subsequently, layout parameters are defined and assigned to the text view. Finally, the text view is added to the parent layout.

The Declarative way of programming UI in Android

@Composable
fun HelloWorld() {
    Text(text = "Hello, World!", 
        fontSize = 18.sp, 
        color = Color.Black,
        modifier = Modifier.fillMaxSize(),
        textAlign = TextAlign.Center)
}

In the above code snippet, we are defining the UI using declarative programming. We define a Composable function HelloWorld that creates a Text element using a single statement. We specify the text, font size, color, and other properties using named arguments. The Modifier parameter is used to specify the layout and positioning of the Text element.

In imperative object-oriented UI toolkits, such as many, UI initialization involves creating a tree of widgets by inflating an XML layout file, followed by instantiating each widget. Each widget retains its own internal state and provides getter and setter methods to allow the app logic to interact with it.

However, in Compose's declarative approach, widgets are designed to be relatively stateless and, unlike imperative UI toolkits, do not expose setter or getter functions. Widgets are also not exposed as objects.

Grasping these concepts simplifies comprehension of the core concept of recomposition which is the process of refreshing solely the essential portions of a Composable function. To put it differently, only the sections of the UI that rely on the modified state are re-composed whenever the state of a Composable function is altered. This enables Compose to upgrade the UI and evade needless work, leading to a more seamless and efficient application. The Compose framework can intelligently recompose only the components that changed.

Here is an example code snippet that demonstrates how recomposition works in Compose:

@Composable
fun TextWithButton() {
   var count by remember { mutableStateOf(0) }

   Column {
       Text(text = "Count: $count")
       Button(onClick = { count++ }) {
           Text(text = "Increment")
       }
   }
}

In the above code snippet, we define a Composable function TextWithButton that displays a text and a button. The count variable is defined using mutableStateOf which allows us to update the value of count and trigger recomposition when the value changes. The Text and Button elements are wrapped inside a Column which arranges them vertically.

When the button is clicked, the count variable is incremented and the Text element is recomposed to display the updated value. The Button element does not need to be recomposed since its state has not changed.

Another example would be the recomposition example made in the official documentation. Android documentation on recomposition .

With recomposition explained we would want to know the benefits of it in the Compose framework.

Benefits of Recomposition

Recomposition offers several benefits that make it a powerful feature in Android Jetpack Compose:

  1. Efficient UI updates: Recomposition allows Compose to update only the necessary parts of the UI when the state of a Composable function changes. This results in a more performant app and a smoother user experience.

  2. Simplified UI code: With recomposition, we can focus on defining the UI and let Compose handle the updates. This leads to simpler and more readable code.

Recomposition fits well with the declarative paradigm shift since it allows us to update the UI in response to changes in state. Understanding the declarative paradigm shift
Declarative paradigm shift.

Conclusion

Recomposition is a powerful feature in Android Jetpack Compose that allows for efficient UI updates and simplified UI code. Gaining knowledge about how Recomposition operates can help us develop superior and high-performing applications.

Thank you for taking the time to read. โค๏ธ๐Ÿ˜

ย