12+ Jahre App-Entwicklung
Alles aus einer Hand
50+ Erfolgreiche App-Projekte

Blog

Jetpack Compose: Google's modern UI toolkit

It's been almost two years since the release of the stable version of Jetpack Compose, but still many developers are skeptical about using this framework in their projects. To answer the question, is it worth using Compose in your projects, let's make a small comparison between Android Views and Jetpack Compose based on typical tasks when developing native Android projects.

Artikelbild für Jetpack Compose: Google's modern UI toolkit

Let's look at Jetpack Compose in the following topics:

Is Jetpack Compose as good as Google says it is?

Google claims that Jetpack Compose is a powerful, intuitive, modern toolkit for building native UI, while reducing the amount of code compared to Android Views to a significant degree. Let's test these conclusions with a simple example of creating a scrollable list of items.

boxes list

We will create a list of boxes using OpenSenseMap Api, with each item of the list must display the name of the box and the number of sensors. On the left, this is what the markup file for the list item in Android Views would look like. Right - creating a list item in Jetpack Compose.

Box list item Android View  Box list item Jetpack Compose

I think it is obvious that code written with Jetpack Compose is not only much shorter, but also visually more orderly. The layout of elements in Jetpack Compose is based mainly on Row and Column, which together with the power of the Kotlin language really simplifies UI creation. Now let's compare the initialization of this list.

Box list adpter Android View  Box list adpter Jetpack Compose

In the case of Android Views, we need to create a BoxListAdapter for the RecycleView, as well as a BoxHolder. In Jetpack Compose, we simply create a function that contains another composable function LazyColumn (similar to RecycleView). Here we simply pass a list of elements and, through a lambda expression, for each element of the list, we call composable function BoxListItem, which we discussed earlier. The difference is huge.

Let's take another example - navigation between the composable functions.

Compose navigation function  Сompose navigation interface

Navigation in Jetpack Compose can use many of the features that we are used to with Jetpack Navigation. However, with Jetpack Compose we now have the ability to navigate between screens (composable functions) with a single Activity without having to use Fragments. It is sufficient to create a NavHost with a Screen Composable component nested in it. We can also define an interface for convenience and define all the necessary routes and parameters in it.

ui folders

Notice how elegantly the files responsible for the UI are now grouped together. Doing away with countless xml files, fragments, and adapters helped achieve this.

Declarative vs. imperative user interface creation in Android

Historically, the hierarchy of Android UI elements has been represented as a widget tree. As the state of the application changes, the UI hierarchy needs to be updated to display up-to-date data. The most common way to update the interface is to traverse the tree using functions, and to change the display by calling the methods of these nodes, that is, changing the internal state of the widget.

Manipulating the views manually increases the probability of errors. If a piece of data is displayed in multiple places, it is easy to forget to update one of the views displaying it. It is also easy to create erroneous states when two updates conflict in unexpected ways. For example, an update might try to set the value of a node that has just been removed from the user interface. In general, the complexity of software maintenance increases as the number of views requiring updates increases.

declarative vs imperativ ui

Designed by Freepik

The declarative approach in development is a new trend that allows programmers to think through the user interface based on the received data. This template focuses primarily on what to show. A declarative user interface requires rethinking the design of the application, accepting that it is possible to rebuild parts of the user interface from scratch rather than changing them. Modern processors are fast enough for this and can even handle animation while rebuilding the entire screen.

In a declarative framework, data state changes trigger a UI rebuild that removes a whole category of state errors and makes it easier to reason about updates. You need to describe what the user interface should look like for a given state, and the framework determines how to do it using default values and context. This greatly reduces the amount of code that needs to be written and makes it easier to repeat.

State holders, UI State and unidirectional data flow

Compose is built based on a unidirectional data flow. Unlike the old UI system, composable functions must be Stateless, not store states - this means that their mappings must be defined by arguments passed to the composable function itself.

unidirectional data flow pattern

Source: Google Documentation

This means that events that come either from the user interface (button clicks, text input, etc.) or from other sources (API calls, callbacks, etc.) are handled by a handler, which then, in turn, updates the state of the user interface, which is passed to the composable functions. Since composable functions have no state, the provided state is what will be used to create the user interface. You can implement a state holder either through a ViewModel or a plain class. let's look at an example using the ViewModel.

ViewModel with UI StateUI State processing

To communicate between ViewModel and composable function, it is preferable to use Observable State data type and MutableState for state management. We can also use LiveData, Flow, converting them to State, using 'observeAsState()' and 'collectAsState()' extension functions respectively. In ViewModel we can define a sealed interface and define in it all necessary states, which will be later checked, and we can substitute the necessary composable function for processing.

The advantages and disadvantages of using Jetpack Compose

Advantages

  • The first advantage is the low barrier to entry. This is primarily due to the fact that development takes place in the same language in which the application logic is developed. The Jetpack Compose team also follows best development practices, reducing boilerplate code while creating quality documentation located on the official Google's documentation site.
  • Compatibility is one of the most important benefits of not having to rewrite the project, but using it where it's needed. The API works both ways - composite functions can be used within XML, and functions themselves can contain XML elements.
  • The lack of XML and imperative programming means low communication and high consistency, resulting in fewer potential problems. One small plus is also lower build time and application size.

Disadvantages

  • More and more developers are paying attention to this library, expressing their approval, some are ready to deal with it in the future, talk about its high potential. But the vast majority of existing systems use standard Android tools and it is impossible to rebuild them instantly.
  • For the reason that Jetpack Compose is still under development, some components are not supported and some features are not stable. The new way of describing the user interface means learning a new testing syntax. Fair enough, but still it is an additional cost of research and training.
  • An important note is also that you have to keep reading about new tools, libraries, and architectures. In addition, you will have to change versions as the system is updated, which will lead to constant code refactoring.

Conclusion

As the engineers at Google said, "You asked us a long time ago, and we did it for you!". In conclusion, Jetpack Compose is a powerful, modern and at the same time intuitive tool for creating UI, which allows you to significantly reduce the time of development of typical routine tasks. Built-in support for material design, dark theme and animation allows you to move to a new level of creating beautiful and user-friendly applications.

I would also like to point out that I am always open to discussions on the current topic, or if you have requests for other topics that you would like to see on our blogs, just write to us.

Igor Gridin

Igor Gridin

Mit über 15 Jahren Erfahrung in der Softwareentwicklung mit Java und Kotlin unterstütze ich im Banken- und Logistik-Bereich unsere Kunden bei spannenden nativen Android-Projekten. Hier schreibe ich über alle neuen Technologien und Trends, die im Bereich der Android-Anwendungsentwicklung auftauchen.

Verwandte Artikel

Voice input facilitates documentation - A hackathon topic
Voice input facilitates documentation - A hackathon topic

Voice input makes it possible to intuitively record food eaten and drunk without having to look at a device or tap. Instead of laboriously entering everything by hand, users can simply record their meals and snacks by voice command. This approach can lower the inhibition threshold and encourage users to continuously document their eating habits. This saves time and encourages regular documentation.

Animations in Jetpack Compose
Animations in Jetpack Compose

Modern applications are becoming more design-centric and therefore end-user-centric. For the user, the technical side of the program is not at all interesting, but rather taken for granted. Attractive design, animation and ease of use, on the contrary, all other things being equal, can make the application more popular among competitors.

How to workaround Xamarin Androids VersionCode limitation

Learn why your Xamarin Android build fails with "Error executing task Aapt: VersionCode is outside 0, 65535 interval" and how to workaround that issue.