Understanding Jetpack Compose

Ananyaa Shrivastava
4 min readJan 8, 2021

--

Basic guide to insights of Jetpack Compose in Android application UI

Jetpack compose is a modern declarative UI toolkit for Android . Compose provides declarative API which helps in easy maintenance and rendering of app UI without mutating frontend views.

The declarative programming paradigm

Historically, the android application widgets used to be arranged in the form of a tree to represent hierarchy. With the change in the state of the application due to sources like user interaction, the current hierarchical tree needed to get updated according to current state manually, using functions like findView ById(), and change nodes by calling methods like button.setText(String), container.addChild(View), or img.setImageBitmap(Bitmap).

This process could lead to more errors ,easy creation of illegal states and missing of views while rendering and increment in complexity with increase in number of views.

Henceforth, there came the existence of declarative UI model , which works by conceptually generating the screen by scratch maintaining only the required changes to be done in UI .This avoids all the hassle and simplifies the process. However, regenerating screen can be expensive, in terms of time, computing power, and battery usage. Compose is intelligent enough to choose the screen data that is to be updated .

But… how and where do we use “Compose”?

Compose can be used to create android app UI using a set of composable data preferably in Kotlin which emit the asserted UI element. Check out this example below !

Composable function that inputs name and returns text widget with generated message
  1. @Composable annotation : informs compose compiler that this function is intended to convert into UI. All composable functions must have it.
  2. Text() : Function called to convert data to text UI. Composable functions create hierarchy by calling other composable functions.
  3. name : String variable taken as input and converted to text message “Hello $name” where ‘$’ takes the variable name given by user.
  4. This function doesn’t return anything.

This function is fast , idempotent(behaves same when provided with same arguments multiple times) and free of side effects.

Since composable functions are written in Kotlin , they are Dynamic in nature. For example, if we wish to greet multiple people with same message , this can be achieved using a list of input names(string).

Greeting list of names with same message (dynamic nature)

The declarative paradigm shift

While using composable , the UI widgets are clearly stateless and don’t expose getter and setter methods unlike traditional android UI . Every time the user interacts and raises an event, the composable function is called with same / different arguments depending upon the data input. If called with different arguments, the composable function transforms the UI according to requirement. This is known as Recomposition.

Recomposition

Consider given example

Every time the button is clicked, clicks is updated by the caller and the text lambda is called by the compose. This is Recomposition. Independent functions are not bothered in this process.

Unbothered functions/lambdas are skipped , hence making recomposition efficient and compose intelligent. But their might be few side effects skipping functions/lambdas. Writing to a property of a shared object, updating an observable in ViewModel and updating shared preferences are few examples.

Points to remember

Compose function can execute in any order and in parallel

Compose functions do not necessarily execute in order. If one compose function has calls to other composable functions, they can execute in any order although compose has the option of recognizing that some UI elements are higher priority than others, and drawing them first.

In above example, all the three functions inside screenmanage can execute in any order ,considering all functions to be self contained(no side effects). If a composable function calls a function on a ViewModel, Compose might call that function from several threads at the same time, considering optimisation, making sure there exist thread safety and no side effects.

Recomposition skips as many composable functions and lambdas as possible and is optimistic.

Recomposition is supposed to execute often considering any change in the input and its optimistic nature. Recomposition wants to make sure that the process completes without the input undergoing any further changes. If the parameter doesn’t change before Recomposition finishes, Compose might cancel Recomposition process and the tree if updated through it, and restart the process with new parameter.

Ensure that all composable functions and lambdas are idempotent and side-effect free to handle optimistic Recomposition.

Composable functions might run as often as every animation frame.

As we earlier discussed, Composable function may execute as often as possible (every animation frame),this may perform expensive operations and create UI junk.

In any situation , if a composable function needs data, it should define parameters for the same. We can then move expensive work to another thread , outside of composition, and pass the data to Compose using mutableStateOf or LiveData.

Jetpack Compose is a great way to create advanced UI with much less hassle and confident features with quick optimisation. However, Jetpack Compose is much more than this article. To experience this amazing toolkit visit Jetpack .

--

--

Ananyaa Shrivastava
Ananyaa Shrivastava

Written by Ananyaa Shrivastava

Android app developer | Full stack web developer | Machine Learning | student | India

No responses yet