Skip to main content

Command Palette

Search for a command to run...

Jetpack Compose: Understanding the Fundamentals

Updated
9 min read
Jetpack Compose: Understanding the Fundamentals
R

Android Dev | Kotlin | Google DSC Lead '21-'22 | Opinions & Bugs are my own :P

Hey everyone!

Welcome to the first blog of my series "Jetpack Compose 101" where we will learn together how to implement various Android features as well as integrate different third-party APIs and functionalities in our Android Applications using Jetpack Compose. To start with, today we will understand the fundamentals of Jetpack Compose with the help of some code snippets and explanations while comparatively analysing it with our traditional XML-based UI development approach.

Introduction

Jetpack Compose is a modern toolkit for building beautiful and responsive user interfaces for Android apps. It is based on the Kotlin programming language and offers a declarative, reactive, and efficient approach to UI development. With Jetpack Compose, developers can create UIs that are easy to understand, maintain, and update and provide a smooth and consistent user experience across a wide range of devices.

In this blog, we will explore the fundamentals of Jetpack Compose and provide a step-by-step guide for getting started with this exciting new toolkit.

Before we get ahead here are some prerequisites needed to fully understand this blog, please go through any of the points you're unfamiliar with before proceeding further for a better understanding.

Prerequisites

  • Basic knowledge of the Kotlin programming language. (Refer here)

  • Some experience with Android development. (Refer here)

  • Android Studio installed on the computer. (Refer here)

  • Optional: Knowledge of the traditional Android View system. (Refer here)

Basics of Jetpack Compose

Traditionally in Android development with Kotlin/Java where we work with either activities or fragments, we have two different files, an XML file to design and write the UI part of our application, and a .kt or .java file in which we code our business logic and how our application will respond and update the user's screen based on our business logic, which has now fundamentally changed with Jetpack Compose.

One of the main differences between the two approaches is that with Jetpack Compose, you build your UI using Kotlin code, whereas, with the XML-based approach, you use XML files to define your UI. This means that with Jetpack Compose, you can take advantage of the power and expressiveness of the Kotlin programming language to build your UI, whereas with XML you are limited to the capabilities of the XML language.

One of the key concepts in Jetpack Compose is the idea of a composable function. A composable function is a special kind of Kotlin function that takes in a set of inputs and returns a hierarchy of UI elements that are used to render the user interface. The inputs to a composable function can include data, parameters, or state, and they are used to control the behaviour and appearance of the UI.

Composable is Jetpack Compose's equivalent of many common XML-based UI elements, such as ButtonView, TextView, EditText, and ImageView.

For example, the Button composable is used to create a button in your UI, the Text composable is used to display text, the EditText composable is used to create an editable text field, and the Image composable is used to display an image.

Here is an example of a simple composable function that creates a button:

@Composable
fun DemoButton() {
        text = text,
        onClick = onClick
}

In this above code snippet, the @Composable annotation is used to mark a function as composable, and the Button function called above is part of the Jetpack Compose library. This function takes in two inputs: the text to be displayed on the button, and a callback function that is called when the button is clicked. The Button function creates a UI element that represents the button, and it is returned by the DemoButton composable function.

Another important concept in Jetpack Compose is the composition. A composition is the result of calling a composable function and is essentially the final UI that is displayed on the screen. It is built from the hierarchy of UI elements returned by the composable function, and it can be updated and rendered dynamically based on changes to the inputs or state of the app.

Here is an example of a composition that uses the DemoButton composable function from the code snippet above :

@Composable
fun MyApp() {
    Column {
        DemoButton("Click me!") {
            // Do something when the button is clicked
        }
    }
}

The Column function is another composable function that creates a vertical container for UI elements. It takes in a lambda that specifies the child elements to be added to the column. In this example, the DemoButton composable function is called inside the lambda and is used to create a button UI element. This button UI element is then added to the column, and the resulting composition is rendered on the screen.

Somewhat similar to the XML-based UI development approach we have in Android, here also the UI is developed by nesting these composable functions within each other, to make a more complex UI as per the app's requirements.

The Composables are nested within each other inside the parenthesis { } and to specify the design aspects and other details of any composable, we pass those details as a parameter of that specific composable in the round brackets ( ).

Below here is a dummy example of what a composable with a more complex UI would look like, notice how we pass the data inside each composable function's round brackets ( ) and multiple composable are nested within other composable functions inside the parenthesis { } to develop the UI within the same Kotlin (.kt) file without the need for any XML file to develop the user interface :

@Composable
fun LoginScreen() {
  Column {
    Text("Welcome to the app!")
    Text("Please log in to continue.")
    TextField(
      value = username,
      onValueChange = { username = it }
    )
    PasswordField(
      value = password,
      onValueChange = { password = it }
    )
    Button(onClick = {
      // Handle login
    }) {
      Text("Log In")
    }
  }
}

In this dummy example, the Column composable is used to lay out the UI elements vertically, the Text composable is used to display some static text, the TextField and PasswordField composables are used to create editable text inputs, and the Button composable is used to create a button that the user can click to log in.

Key Features of Jetpack Compose

One of the main advantages of Jetpack Compose is its reactive nature. This means that the UI is automatically updated whenever the underlying data or state of the app changes. This eliminates the need for manual updates and makes it easier to build dynamic and responsive UIs.

Another key feature of Jetpack Compose is its support for declarative UI development. This means that developers can describe the desired UI using a simple and concise Kotlin code, without worrying about the details of how it will be rendered on the screen. This makes it easier to focus on the design and functionality of the UI, and reduces the amount of boilerplate code that needs to be written.

For example, consider the following code:

@Composable
fun DummyList(items: List<String>) {
    Column {
        items.forEach { item ->
            Text(text = item)
        }
    }
}

This composable function DummyList creates a column of text labels, one for each item in the given list of strings. It uses the forEach method to iterate over the items in the list, and for each item, it calls the Text function to create a text label. This code is easy to understand and maintain, and it clearly expresses the intent of the developer.

Getting Started with Jetpack Compose

To get started with Jetpack Compose, you will need to have the latest version of Android Studio installed on your computer. Now, create a new Android project in Android Studio and select "Empty Compose Activity" as the starting point, which will generate a boilerplate Jetpack Compose codebase from where you can get going.

Note: This may change depending on when you are viewing this blog or the version of your Android Studio, if you don't see an "Empty Compose Activity" in the projects panel while creating a new project you can Google this step.

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            ComposeDemoTheme {
                // A surface container using the 'background' color from the theme
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colors.background
                ) {
                    Greeting("Android")
                }
            }
        }
    }
}

@Composable
fun Greeting(name: String) {
    Text(text = "Hello $name!")
}

@Preview(showBackground = true)
@Composable
fun DefaultPreview() {
    ComposeDemoTheme {
        Greeting("Android")
    }
}

This is the default boilerplate code generate by Android Studio for Jetpack Compose, you will already see a lot of similarity with the traditional XML based Kotlin file's code, apart from that you can see two new functions here, Greeting() and DefaultPreview().

Here, as you can already understand by the demo examples from above, Greeting() is a composable function that creates a text label with a greeting message, whereas DefaultPreview() is a preview function that is used to generate a preview of the Greeting composable function.

This is how we can see the preview of our composable function just like we see the preview of DefaultPreview() here below :

Conclusion

To conclude, In this blog, we have learned about Jetpack Compose, what it is and how it is in comparison to XML-based UI development in Android. We have also explored the basics of Jetpack Compose in detail with a few code examples and explanations, including the concepts of composable functions and compositions, and we have discussed some of its key features, such as its reactive nature and support for declarative UI development. We have also seen how we can get started with Jetpack Compose in an Android project. This blog will be a good starting point for anyone with a basic knowledge of Android Development in traditional XML-based development, I will link some great resources to learn more about Jetpack Compose from the sources I have personally used and which are great for beginners.

Resources

Thank you!

If you have made it this far, thanks for taking the time and reading out this blog, this is my first technical blog and I would love to hear from you on how I can improve my future blogs of this series, please leave feedback here if possible. I'll be happy to connect with you on my socials below :

Twitter : @shoxxxxie
LinkedIn : Rishabh Mehta

A special thanks to Google Devs India and the Android Educators Community India team for providing me with this opportunity to learn and help other developers learn more about the best practices in modern Android Development. :D