Blog Infos
Author
Published
Topics
, , , ,
Published
Unsplash@anniespratt

 

Jetpack Compose is a modern UI toolkit for Android that simplifies and accelerates UI development. One of its key advantages is its declarative approach to building UIs, allowing developers to create components in a natural, Kotlin-centric way.

This means developers define what the UI should look like for a given state, and Compose handles the updates automatically. This approach integrates seamlessly with Kotlin’s language features, allowing the use of logical constructs such as if and when statements directly within the UI definition, resulting in more intuitive, readable, and maintainable code.

Unlike traditional XML-based view systems or other UI libraries, Jetpack Compose comprises three main structures: CompilerRuntime, and UI. The Compose Compiler interprets and processes the code written in Composable functions during compile time, transforming them into an efficient, reactive UI representation. This design allows developers to create UI components in a more logical and readable way by leveraging the full capabilities of Kotlin, such as combining UI with conditional logic seamlessly.

In this article, you’ll explore the concept of declarative UI and take a closer look at Jetpack Compose’s approach compared to traditional XML-based view systems. This topic has been raised and featured in Dove LetterDove Letter is a subscription repository where you can learn, discuss, and share new insights about Android and Kotlin. If you’re interested in joining, be sure to check out “Learn Kotlin and Android With Dove Letter.”

What is Declarative UI?

The term declarative UI refers to a programming paradigm that focuses on describing the desired outcome — specifically, what the user interface should look like at a given application state — rather than detailing how to implement it. This approach allows developers to define the UI by its intended state, leaving the framework to manage the updates and rendering accordingly.

Declarative UI has already been adopted across many platforms, including Flutter and SwiftUI, for its ability to simplify code and improve readability. So, what is Declarative UI all about? Let’s first examine its key characteristics below:

  1. Defining Components with Functions or Classes: Declarative UI encourages defining user interface elements as components, which can be represented by functions or classes. These components not only describe the UI layout but also encapsulate essential functionalities. A core benefit is the reduction of the language gap between traditional markup languages like XML and native programming languages like Java or Kotlin, resulting in more seamless and integrated component development.
  2. Managing State for Components: In a declarative UI framework, state management is handled internally. This means the framework is responsible for tracking the state of each component and automatically re-rendering the UI when the state changes. Developers only need to define how the UI looks for a given state, and the framework handles the updates when the state changes.
  3. Binding Data Directly to Components: Declarative UI allows developers to bind model data to UI components directly. This is typically done programmatically, meaning the data flows directly from the model to the UI without manual intervention, leading to cleaner, more efficient code.
  4. Ensuring Component Idempotence: One of the key characteristics of declarative programming is idempotence. In this context, it means that a component’s output will always be the same for the same input, no matter how many times it is invoked. This property enhances component reusability and ensures consistent behavior across the application.

Now that you understand the concept of declarative UI, it’s time to explore why Jetpack Compose is a declarative approach by comparing it with the traditional XML. This comparison will highlight how Compose’s declarative nature offers advantages in readability, state management, and streamlined UI development over the imperative style of XML-based views.

Jetpack Compose vs. XML

Jetpack Compose embraces a declarative UI approach, allowing you to write UI code logically by embedding state conditions directly in Kotlin. This means that the UI is automatically updated based on the current state, making it easier to manage and reason about. Let’s explore why this approach is beneficial by looking at a simple example: a button that displays the number of times it has been clicked.

@Composable
fun Main() {
var count by remember { mutableStateOf(0) }
CounterButton(count) {
count++
}
}
@Composable
fun CounterButton(count: Int, onClick: () -> Unit) {
Button(onClick = onClick) {
Text("Clicked: $count")
}
}
view raw declarative.kt hosted with ❤ by GitHub

We can break it down one by one why it’s a declarative UI like the reasons below:

  1. A function annotated with @Composable is interpreted and transformed by the Compose Compiler. This fulfills the first principle of declarative UI, which involves defining components using functions or classes, as discussed earlier.
  2. Functions like remember, provided by the Compose Runtime, offer mechanisms for state management, effectively managing the lifecycle of each composable. This satisfies the second characteristic of declarative UI—managing states for components.
  3. The count parameter in the CounterButton composable function is directly tied to the UI components, showcasing binding data directly to components—the third key characteristic of declarative UI.
  4. The CounterButton composable function consistently renders the same UI output for a given input, ensuring component idempotence. This matches the fourth characteristic of declarative UI, which aims for predictable and reusable components.

Now, let’s look at how to implement the same UI using the XML approach:

<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="horizontal"
android:padding="4dp">
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="Clicked: 0" />
</RelativeLayout>
view raw xml.xml hosted with ❤ by GitHub

Job Offers

Job Offers

There are currently no vacancies.

OUR VIDEO RECOMMENDATION

, ,

Kobweb:Creating websites in Kotlin leveraging Compose HTML

Kobweb is a Kotlin web framework that aims to make web development enjoyable by building on top of Compose HTML and drawing inspiration from Jetpack Compose.
Watch Video

Kobweb:Creating websites in Kotlin leveraging Compose HTML

David Herman
Ex-Googler, author of Kobweb

Kobweb:Creating websites in Kotlin leveraging Compose HTML

David Herman
Ex-Googler, author o ...

Kobweb:Creating websites in Kotlin leveraging Compose HTML

David Herman
Ex-Googler, author of Kob ...

Jobs

At first glance, an XML layout may indeed seem very similar to a declarative UI approach, and that’s because XML itself is inherently declarative. In XML-based UI development, like that used in Android’s traditional layout system, developers describe what the UI should look like, rather than detailing how the rendering happens, which is a fundamental characteristic of declarative programming.

However, the difference lies in how state and logic are handled. In XML, you define the structure and attributes of the UI, but the state management and UI updates are handled separately in imperative code using Java or Kotlin. This results in a clear disconnect between UI definition and behavior, often leading to a more complex process for dynamically updating the UI.

var counter = 0
binding.button.setOnClickListener {
counter++
binding.button.text = counter.toString()
}
view raw imp.kt hosted with ❤ by GitHub

In contrast, Jetpack Compose not only allows developers to define the UI in a declarative way but also integrates state-driven updates seamlessly within the Kotlin language itself. This means you can define both the UI and how it responds to state changes in the same place, making the code more cohesive and eliminating the need for separate imperative handlers. Essentially, Compose provides a declarative UI approach with an integrated state-management system, which makes it more modern and powerful compared to the traditional XML approach.

Advantages of Declarative UI

Let’s examine the advantages of using a declarative UI approach.

  1. Consistency Between UI and Business Logic: By using declarative UI, developers can leverage the same language (e.g., Kotlin, Swift) to define both the business logic and the UI components. This consistency eliminates the need for separate markup languages like XML, streamlining the development process and improving overall productivity.
  2. Automatic State and UI Management: Declarative UI frameworks automatically handle state management and UI invalidation. In systems like Jetpack Compose or SwiftUI, when the state changes, the UI is automatically invalidated and re-rendered. This reduces the need for manual intervention, simplifying the logic and reducing errors.
  3. Enhanced Reusability through Idempotence: Because declarative UI components are idempotent, they always render the same result for the same input. This makes components highly reusable, allowing developers to create consistent, modular UIs that can be easily reused across different parts of the application.
  4. Seamless Data Binding Between Domain and UI: Declarative UI allows for direct binding of domain-level data to UI components. Developers focus on what the UI should display, rather than how to update it when the underlying data changes. This makes development more intuitive and results in cleaner, more maintainable code.

You’ve explored the advantages of a declarative UI. However, as noted in the point on Automatic State and UI Management, this feature can sometimes be a double-edged sword. Without a solid understanding of state management, developers may unintentionally cause performance overhead, leading to excessive or unnecessary re-compositions. This challenge is not unique to Jetpack Compose — it is also common in frameworks like React, which similarly rely on declarative state-driven UI updates.

Jetpack Compose was inspired by several other frameworks, including React, Litho, Vue.js, and Flutter, as noted by Jim Sproch, one of the key contributors to Jetpack Compose.

Conclusion

In this article, you’ve explored why Jetpack Compose is considered a declarative UI framework, the core principles of declarative UI compared to traditional XML-based development, and the key advantages of adopting a declarative approach in UI design.

Declarative UI is not a brand-new concept; it has been utilized by several other frameworks for years. Frameworks like React, Flutter, and Vue.js have adopted this approach, which focuses on defining what the UI should look like based on its current state. It’s important to understand declarative UI thoroughly to leverage its full potential, ensuring that you can maximize its advantages, such as improved readability, ease of maintenance, and streamlined state management.

If you’d like to stay updated with the latest information through articles and references, tips with code samples that demonstrate best practices, and news about the overall Android & Kotlin ecosystem, check out Dove Letter and ‘Learn Kotlin and Android With Dove Letter’. Also, If you have any questions or feedback on this article, you can find the author on Twitter @github_skydoves or GitHub.

As always, happy coding!

— Jaewoong

This article is previously published on proandroiddev.com

YOU MAY BE INTERESTED IN

YOU MAY BE INTERESTED IN

blog
It’s one of the common UX across apps to provide swipe to dismiss so…
READ MORE
blog
In this part of our series on introducing Jetpack Compose into an existing project,…
READ MORE
blog
In the world of Jetpack Compose, where designing reusable and customizable UI components is…
READ MORE
blog
Hi, today I come to you with a quick tip on how to update…
READ MORE
Menu