4 reasons Jetpack Compose is better than XML

Nishant Aanjaney Jalan
3 min readMay 6, 2022

--

Jetpack Compose is the modern UI-tooling from Google. It’s first stable release was in July 2021 and so far, many Kotlin developers are loving this new way of designing the UI in Android. Let’s take a look at some great examples of Jetpack Compose and how it differs from traditional XML.

Declarative UI

Till date, we used Imperative UI in Android. First we fetched the element and get the contents, then modify and lastly update the same element. The connection between Android and XML is also not performant with findViewById() or even kotlinx.synthetics. Although the introduction of ViewBinding and DataBinding is good, the setup required is tiresome.

Declarative UI is when the state of the screen is pre-defined and the UI elements will reload when it listens to any changes made to this state. Let’s take a simple button counter example:

class MainActivity: ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
Box (modifier = Modifier.fillMaxSize().background(Color.White)) {
MainScreen()
}
}
}
@Composable
fun MainScreen() {
var count by remember { mutableStateOf(0) }
Column(
horizontalAlignment = Alignment.Center,
verticalArrangment = Arrangement.Center
) {
Text(text = count.toString())
Spacer(modifier = Modifier.height(16.dp))
Button(onClick = { count++ }) {
Text(text = "Click me")
}
}
}
}

Every time we click on the button, the value of count changes, causing the Composable function to recompose for the updated UI. We need to make sure that the states are inside a remember block because after recompositing, the previous state is lost otherwise.

Say NO to RecyclerView

Instantiating RecyclerView in XML had alot of boilerplate code. We needed to have a layout for the item, the ViewHolder and the Adapter and the configuration in the Activity/Fragment. With Jetpack Compose, the need for the boilerplate code is no longer required.

class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
val messages = listOf(
Message("Kevin", "I am on my way"),
Message("Natasha", "Don't leave the stove on"),
Message("Peter", "He did it again!")
)
LazyColumn(modifier = Modifier.fillMaxSize().background(Color.White)) {
items(messages) { message ->
MessageRow(message)
}
}
}
}
@Composable
fun MessageRow(message: Message) {
Column(modifier = Modifier
.fillMaxWidth()
.border(1.dp, Color.Black)
.padding(8.dp)
) {
Text(text = message.receiver, fontWeight = FontWeight.Bold)
Text(text = message.content)
}
}
}

LazyColumn is a replacement for a vertical RecyclerView. The screen will render the composables only when they appear on the screen — good for long lists from APIs. And since Jetpack Compose is a Declarative UI framework, the composables will be redrawn on state changed.

Navigation

Navigation in normal XML was a headache. With fragments, we had to have the instance of the class, with bundles and replace the fragment inside of a container. With the introduction of the Jetpack Navigation Component, it was no better as the configuration was not ideal and unavoidable. Jetpack Compose to the rescue!

class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
val navController = rememberNavController()
NavHost(startDestination = "home") {
composable("home") {
Home(navController)
}
composable("profile") {
Profile(navController)
}
}
}
}

@Composable
fun Home(navController: NavController) { /* code */ }

@Composable
fun Profile(navController: NavController) { /* code */ }
}

Although, the Navigation of Jetpack Compose could arguably get a reform with the way it’s used, this is a great alternative to the Navigation we used to have with XML.

Animations

You cannot have a topic regarding Jetpack Compose and not introduce animations. Animations has been the best feature of Jetpack Compose. XML was not built to create complex animations but Jetpack Compose brings it to the table with a great interface.

There are tons of different ways you can animate properties and composables. You can trigger the visibility with different enter/exit effects with AnimatedVisibility, creating transitions between elements, and most of all using the animate*AsState, where * represents a data type like Int or Float.

Jetpack Compose provides you a variety of the different configurations that you can use to customize the animation you would want in your screen.

Conclusion

No, with the introduction of Jetpack Compose, it doesn’t mean that XML is deprecated. Google took them three years to officially declare Kotlin as their language and introduced a UI tooling kit that can run just in Kotlin. Similarly, within a few years, Compose will be the preferred way of dealing with UI and Google will create new components which is possible to render only if you use Jetpack Compose.

--

--

Nishant Aanjaney Jalan

SWE Intern@JetBrains | UG Student | CS Tutor | Android & Web Developer | OCJP 8 | https://cybercoder-naj.github.io