This article was first published on Android platform Kotlin, welcome to follow!

Hello, I’m Wanbo. Today we’re going to talk about Jetpack Compose.

After the Beta release, I first read the official documentation of Jetpack Compose, watched all the videos about the official release of Jetpack Compose on Youtube, and then participated in the official organization #AndroidDevChalleng for a practical experience.

This year, we will focus on Jetpack Compose. There will be four weeks of challenges. Each week, we will have a different topic to familiarize you with Jetpack Compose from different dimensions.

My current understanding of Jetpack Compose is not very deep, but after reading the official document, I think Jetpack Compose has a lot of design aspects that I am very impressed with, so I can’t wait to share with you.

1. Let’s start with my own advice for using Compose

You can keep an eye on it, any official learning content on the line, have a general impression to write a Demo can play, don’t be radical in the official project to use it.

I have written two independent projects for iOS before. At the beginning, I used SwiftUI to write them. It was very cool when I wrote them, because they were new things after all, and I had strong curiosity and sense of achievement.

Because there are so many bugs, I spend most of my time solving bugs, and most of the time I don’t know if it’s a Bug or a Bug I wrote. Of course, this is also due to the closed source of iOS itself.

Before Jetpack Compose develops its new feature, its first task is to translate all the existing View components. The translation process is also a process. First, it will complete the translation of the surface of the View, such as how to write a TextView. How to write a Layout, how to write a list, after the translation of View layer things, such as View Listener, various events.

In my opinion, most of the functions in the inner layer will not be fully supported until Release 2.0. The invisible functions will be missing, and there will be a lot of unpredictable problems. Then you will search on the Internet for how to solve the XXX problem, and you will find that everyone is just as confused as you, and don’t know what to do, because this is the bug itself. Only official repair and support can completely solve the problem.

Another point to pay attention to is the ecology. Before the ecology is rich, you can only choose some officially supported solutions. If you encounter special customized functions, it may increase your development cost several times.

So be careful about using it in a formal project.

2. Differences between traditional View and Jetpack Compose

There are two main differences: UI build and UI refresh.

Imperative programming is defined in Wikipedia as the use of statements that change the state of a program to achieve certain functions and effects. Declarative programming is defined as expressing the logic of a computation without describing the flow of its control.

In plain English

Imperative programming is a process of telling the system what to do and how to do it in order to achieve the desired function.

Declarative programming hides the process. You just manipulate the basic elements, combine them, and build what you want.

Using declarative UIs to write interfaces can greatly reduce the amount of code, but also improve the error tolerance rate, the entire UI building logic is clearer and easier to read.

Another difference is in the UI refresh layer

In the traditional View system, the UI state is updated by calling some set methods of the View. This is a manual PROCESS of UPDATING the UI. The maintenance of this process usually increases with the increase of the COMPLEXITY of the UI, and it is very error-prone.

Compose’s dynamic UI is tied to data, which automatically updates the state of the UI when the data changes. There is no need to manually update the state of the UI, even if the UI is complex, and we only need to focus on the data update logic.

From UI construction to UI refresh, it is actually a process from complexity to simplicity, allowing developers to focus more on the development of business logic.

3. Compose’s core design concept

We’ll talk about UI building and refreshing, but we’ll introduce two new terms: composition and reorganization.

The construction of the UI

In Compose, the View is no longer an object but a @composable token.

The UI is built by combining different @composable elements. For example, if we want to implement a Text list, we can select the Column element (vertical list) and declare the Text element internally, which is very fast. All of the UI effects can be implemented through the combination of basic elements built into Compose.

The @composable elements are independent of each other and do not have inheritance, which is completely different from traditional imperative programming. Element differentiation is also achieved through composition, which implements a new element structure by combining different built-in base elements.

Compose has a very core class Modifier, which can be understood as element enhancement or element modification, and each @composable element can accept a Modifier that modifies the actual presentation of the element by defining different modifiers.

It is recommended that you implement a new custom element through the combination of elements, and then pass in different Modifier to achieve the reuse effect of custom View.

The UI refresh

In Compose, the UI refresh is done by rerendering the entire screen, which is how all declarative UI refresh pages work.

Compose, however, makes only the necessary changes to the elements that need to be changed based on the changes in the data. The process of recomposing the composite UI by changing the data is called recombination. When the data is updated, elements unrelated to the data modification are re-rendered from the entire screen, as the @Composable method is very fast, idempotent and has no side effects.

A very important one is idempotent, which means a function that can be executed repeatedly with the same parameters and get the same result. These functions do not affect system state, nor do they have to worry about system changes caused by repeated execution. In other words, @composable elements that have nothing to do with data modification are not recomposed during screen re-rendering.

The Compose compiler will mark each @Composable element when it is initialized and then intelligently select the element to be composed based on whether the data has been modified.

We can also add additional auxiliary information to help Compose’s compiler make more accurate judgments. A typical example would be in a dynamic list, where we add a single entry at the end of the list, and the compiler considers the previous entry unchanged and reassembles the last element.

But when we insert data at index == 0, the compiler will assume that the entire list has been modified because its default tag records the position, and inserting data at 0 means that the entire list needs to be reorganized.

At this point, we can add a key to the contents of the list, usually a unique ID, to tell the compiler that we still need to determine whether the ID has changed. In this case, the compiler only reassembles the first element, and the subsequent elements still use the previously generated instance.

The only way to refresh the UI in Compose is by recomposing, which is determined by whether the data bound to the @Composable element has changed.

Reorganizations need to pay attention to

Reorganization means that the system will re-call the execution of the @Composable element methods, which can happen at any time and very frequently. All the execution of the @Composable methods is out of order and parallel, which we need to be aware of.

So in the @composable method, any Local variables, any dynamic calculation methods, and any logic for updating data need to be carefully considered, otherwise unpredictable errors will occur.

In the process of recomposing, the Local variable will fail and the dynamic calculation method will be called many times, which is a big bug. Hopefully Android Studio will implement strict code checks in the @composable method to help check for potential errors while writing.

3. The combination of UI and data that is officially recommended

A process similar to a single data stream

The dynamic @composable element is controlled by data passed from the upper layer, and interactive events are sent back to the upper layer in the form of blocks, which update data on the upper layer to dynamically update the UI. Data delivery is top-down, and interactive events delivery is bottom-up.

According to this logic, we need to define mutable data in the ViewModel, define methods to modify the data, pass the data up to the actual UI, then pass the UI interaction events up, and update the data by performing the methods to modify the data in the uppermost ViewModel.

But this actually creates a new problem, as the @composable method can become very overloaded when our UI is extremely complex.

This requires you to implement a new element structure using different built-in base elements, optimizing the structure of the code through composition, and so on.

The last

While Jetpack Compose looks like something new at first glance, when you read the documentation, it makes sense. The point is that Compose speeds up the overall Android development process from complex to simple, allowing us to focus on the implementation of business logic.

Including the rapid iterations of Jetpack over the years, the goal is the same, and Compose and the previous set of architectural design rules in Jetpack can be used seamlessly, just changing the logic we used to write the UI.

Jetpack Compose is definitely not the end of Android UI development, but it’s definitely a big step forward in the Android ecosystem.

Of course, if you want to use the same phrase in a formal project, be careful and wait.

For Compose, there is a lot of content that cannot be covered completely in one article. If you have other concerns, please continue to comment in the comments section. I will write an answer article for you next time

Welcome to Android! Kotlin!