Unleashing the Power of Jetpack Compose: A Journey into Modern Android Development

author avatar

Sergej Mihic

July 12, 2023

5 min read

The Android development landscape is constantly evolving, and staying up-to-date with the latest trends and innovations is essential for any developer. In today’s fast-paced world, users demand seamless and engaging experiences, making it crucial for developers to leverage cutting-edge tools and technologies.

Jetpack Compose is a breath of fresh air to all of those bug-riddled XML layouts, providing a more intuitive and flexible way to create dynamic and responsive user interfaces.


It might be due to occasional frustration with XML but it felt liberating to code in Compose because of how feature-rich it is and how easy it is to implement those features.

NEW, YET SO FAMILIAR

As someone who has been fortunate enough to complete a variety of courses across different subjects during my education (read as: “Jack of all trades, master of none”), I felt comfortable with Compose. It takes best practices from plenty of those technologies and it feels fairly familiar. On the other hand, sometimes it doesn’t even feel like I’m writing an app for Android.

I feel like you can develop a Compose app with “If a need arises, creativity will follow” in mind. 

If you need something, just do it by easily creating your custom element. No need to be held back by Material Design (or lack of it) just because it is a headache to make your own UI element.

WHAT and NOT HOW?

This is how Google describes working with Compose. It means we are writing what the UI should do, not how it should do it. UI is built on states that control recomposition (redrawing of the elements), but only in elements whose states changed. The What is enforced by Composable functions, which make UI elements.

Text(text = "Some random text",
   modifier = Modifier
       .padding(bottom = 8.dp)
       .align(Alignment.CenterHorizontally)
       .clickable {
           //do something
       }
)

For example, this function writes Text with  “Some random text” value, 8dp bottom padding, and centrally aligned content which also does something on click. Exactly in that order. 

Why is it so important to emphasize the order? Because of that modifier argument, you saw above. The modifier is as well a massive part of the What concept.

Let’s look at another example:

fun Screen() {
   Box(modifier = Modifier.fillMaxSize())
   {
       Box(
           modifier = Modifier
               .width(300.dp)
               .height(400.dp)
               .background(Color.Red)
               .background(Color.Yellow)
       )
   }
}

It paints the box red first and then yellow

Let’s put an offset in between color changes to demonstrate it better.

fun Screen() {
   Box(modifier = Modifier.fillMaxSize())
   {
       Box(
           modifier = Modifier
               .width(300.dp)
               .height(400.dp)
               .background(Color.Red)
               .offset(x = 50.dp)
               .background(Color.Yellow)
       )
   }
}

As you can see from this screenshot of the Layout Inspector it painted the box red (that exact position) and then moved it and painted the new position yellow. You can see as well that the red area doesn’t belong to the box anymore because it was painted before the offset.

You can find more on modifiers at: https://developer.android.com/jetpack/compose/modifiers


Almost every View Material Design element has its Compose counterpart, but I would like to highlight Lazy Rows and Lazy Columns. They serve as a substitute for a RecyclerView. Let’s jump to an example right away.

private val list = listOf(12, 5, 7, 16, 4)
private val colors = listOf(Color.Red, Color.Blue, Color.Yellow, Color.Green)

@Composable
fun Screen() {
   Box(modifier = Modifier.fillMaxSize()) {
       LazyColumn(modifier = Modifier.border(10.dp, Color.Black, RectangleShape)) {
           items(list) { number ->
               ExampleElement(number = number)
           }
       }
   }
}

@Composable
fun ExampleElement(number: Int) {
   Box(
       modifier = Modifier
           .width(100.dp)
           .height(100.dp)
           .background(colors.random())
   ) {
       Text(text = number.toString(), modifier = Modifier.align(Alignment.Center))
   }
}

No need for setting up adapters or RecyclerViews. Just call Composables within items() and do all the work with Composables and Modifiers.

Lazy Rows and Lazy Columns are very similar to Rows and Columns, but are much more memory efficient because they compose only visible items, just like RecyclerView.

Navigation is, mildly put, underwhelming. Disregarding my dislike of XML, XML navigation is undoubtedly better. You can only pass primitive types as arguments to the navigation component. It is possible to convert your Serializable or Parcelable to String or make a custom NavType every time, but it is bothersome. Also, wherever I initialized ViewModel, it felt like there needed to be a better place to do so.

Although I like to uniform my projects, I would rather go with tried and true XML Navigation this time, at least until they bring its navigation to a tolerable level.

Overall I enjoyed using Compose, and I’m looking forward to seeing how it develops further. I am prepared to overlook certain aspects, such as navigation, considering that it still has considerable room for improvement. Nevertheless, it has come a long way already.

FINAL THOUGHTS ON JETPACK COMPOSE

Jetpack Compose has brought about a breath of fresh air to Android development, offering numerous advantages. Its thriving community ensures a wealth of resources and support, while its intuitive nature enables easier development with reduced boilerplate code. The freedom from XML layouts has been a welcome change for many developers. 

However, it is important to acknowledge that Jetpack Compose is still in its development stage, and there may be some limitations. Some basic features might be lacking, and navigation can be an area of improvement. 

Despite these cons, the future of Jetpack Compose looks promising, and with each update, it is expected to address these shortcomings and become an even more powerful framework for Android UI development. 

Follow us on the social media channels that are listed down below and stay up to date with insights, good practices, and daily activities from our flock.

Care to share?


Unveiling the Dev Journey: Experiences in Product vs. Outsourcing Development

Business

Unveiling the Dev Journey: Experiences in Product vs. Outsourcing Development

In the dynamic landscape of the Serbian IT community, our team finds itself at the intersection of two compelling narratives: outsourcing and product development. Beyond being an outsourcing hub, Serbia is home to numerous companies that have crafted their successful products, adding a unique vibrancy to the IT community.  Right now, some of our team […]

5 Years of Crystal Pigeon: A Journey of Friendship, Challenges, and Success

Uncategorized

5 Years of Crystal Pigeon: A Journey of Friendship, Challenges, and Success

Time flies, doesn’t it? You’ve probably heard this phrase quite often, especially in the business world. It’s a sentiment we’ve been expressing a lot in the past month as we celebrated the fifth birthday of Crystal Pigeon. We won’t talk too much on this topic, but we feel the need to express our gratitude and […]