A few months ago, Jetpack Compose was promoted to beta allowing everyone to get a glimpse of what the future state of Android development could look like. Following this announcement, a new Android Developer Challenge was launched to promote the new framework through a series of four challenges with a chance to win exciting prizes. Since the announcement was a great interest to me, I took part in the challenge to learn more about the upcoming framework. In this blog post, I'll share my initial experience with Jetpack Compose.
Jetpack Compose
Jetpack Compose is a new declarative user-interface (UI) framework within the Android ecosystem to help create beautiful UI with less code. As opposed to the traditional imperative UI development where the user-facing views are created in a tree-like structure of widgets through the inflation of an XML layout file, Jetpack Compose provides Kotlin APIs to create composable functions that emit the UI in a declarative manner. In a sense, the views are initially created in the composition stage and only then the necessary changes are applied whenever the state has changed. Similar to SwiftUI, the core programming language is responsible for creating the UI which favours both the ease of use as well as the notion of reusability when it comes to development.
What Surprised Me
There were a few things that surprised me when I started working on the Android Developer Challenge. The first one was working with the preview mode where I could visually see the changes as soon as I applied them. This could drastically reduce the development time as I would no longer have to re-run my application on a device. In addition to that, working with Jetpack Compose felt very similar to Flutter. Both frameworks share the same look-and-feel when it comes to how the UI is so easily presented in the source code. Finally, Jetpack Compose is supported by a wide range of Jetpack libraries that have the corresponding Compose dependency, such as Jetpack Navigation for Compose. This will make it easier for Android projects to integrate the new framework without much effort. If a project is following an architecture pattern that separates the UI from the business logic layer, then Jetpack Compose can replace the Activity or Fragment source code with Composable functions that will handle the UI and state, without impacting the business logic.
Challenge 1 - Thinking in Compose
In the first challenge, the task was to create a puppy adoption application with two screens. The first screen will showcase a list of all the puppies followed by the puppy's detail on the second screen. The challenge focused on the basics of Jetpack Compose and the building blocks of creating UI from the Kotlin APIs. Views, such as Text, are added in the Composable function annotated by the Composable tag. This tells the framework that this function takes data as input and emits UI elements.
Jetpack Compose takes a series of Composable functions and draws them during the composition stage with some initial data. If the state has changed at some point, the changed composable function is executed again with new data which is then redrawn. Jetpack Compose automatically handles this process of recomposition very efficiently and only updates the view that have changed since last redraw.
Source code of the first challenge.
Challenge 2 - Managing State
In the second challenge, the task was to create a countdown timer application using state in Jetpack Compose. A state is any piece of information that can change at any time. Since the view can be recomposed multiple times at any given time, the remember keyword binds the state to the local storage allowing it to survive the recomposition. In addition, the observeAsState keyword adds a LiveData on an object and observes when the object has changed.
The timer application made use of state, remember and observeAsState in its implementation. The state kept track of whether the app was in a countdown mode or whether the user has yet to start the timer. Based on this, the specific UI was shown to the user. When the timer had started, the viewmodel was responsible for launching the thread that would count down and update the object that the LiveData was bound to. Whenever the time value changed, the UI would redraw the Text view that held the timer value.
Source code of the second challenge.
Closing Remarks
Working with Jetpack Compose is quite different from traditional UI development for Android. There are a lot of new keywords and principles added when working with the new declarative framework. It could be a learning curve, but I am excited to see what the future holds for modern Android development. In the meantime, I got to enjoy a cool prize from the Android Developer Challenge.