Jetpack Compose: State Hoisting

How does the app’s state determine what is displayed in the UI?

Mansi Shah
Jetpack Composers
Published in
3 min readOct 20, 2022

--

As a part of a self-learning program launched for all developers in my company, I took a course Android Jetpack Bootcamp 2022 from Udemy. I would like to share my learnings from that course with you all.

I will start with Composition and Recomposition followed by the type of states & APIs provided by Jetpack Compose.

Composition & Recomposition

Composition: The UI of your app is initially built by running composable functions in a process called Composition.

Composable functions have their own lifecycle that is independent of the Activity lifecycle. Its lifecycle is composed of the events: enters the Composition, recomposing 0 or more times, and then leaving the Composition.

Recomposition: When the state changes, UI will be regenerated and a recomposition is scheduled. Recomposition is when Compose re-executes the composable functions with new data whose state might have changed and created an updated UI.

State in Compose

The state determines what is shown in the UI at any particular time. An app’s “state” is any value that can change over time. Jetpack compose has a reactive approach for storing state in a variable, we need to use MutableStateOf or observable like LiveData, Flow, etc for the same.

Let’s take an example of a Counter app to understand State, which increases the count when a button clicks.

  • MutableStateOf: To indicate to Compose that it should track an object’s state, the object needs to be of type State(immutable) or MutableState(mutable).

Above as you can see, MutableStateOf does the work but it is not the best way, because in jetpack compose every composable function recomposes independently so it can give unexpected results if we use the same variable with multiple composable functions. Here comes the remember API in the picture.

  • remember API: To instruct Compose to retain and reuse its value during recompositions, you need to declare it with the remember API. It is used as a guard against the recomposition to avoid the state being reset.

The above code won’t work if we rotate the device from let’s say portrait to landscape. It will not retain the state of the count variable. Here comes the rememberSavable API in the picture.

  • rememberSavable API: It is used to save values that you need if Android OS destroys and recreates the activity. Use rememberSaveable to save values during recompositions AND configuration changes. Use “by” Property Delegation.

There are two types of composable functions available:

  • Stateful Composable —it defines the internal state & controls it. A composable function with an internal state is called a Stateful Composable.
  • Stateless Composable — it doesn’t hold any state. Stateless Composables are used to display static UI.

Let’s understand Stateful composable in detail with state hoisting pattern.

State Hoisting

It is a pattern of moving the state of the composable to its caller to make it stateless and sending the event(i.e. onClick event) from caller to composable.

Two parameters should be added while applying state hoisting to the composable function:

  1. Current value to display
  2. An event that requests a change of current value

In the above code, we added a currentCount as the first param to display text on the Button and a updateCount lambda function as a second param to increase a count on button click in the MyButton composable function.

UDF (UniDirectional Data Flow)

In this design pattern, the State goes down while the Event goes up. In the above code, currentCount goes down to the MyButton function, and the button’s onClick event updateCount goes up to MainActivity’s setContent method.

State hoisting is the main pattern used in UDF architecture. It provides a single source of truth.

Pros

  • Easy unit testing
  • Avoid the risk of sharing state by encapsulating it

Final Code

Final Result

That’s a wrap for now! Many more Jetpack Compose topics to come 💥
You can access the source code from Github.
I hope you find this blog helpful.

--

--

Mansi Shah
Jetpack Composers

Lead Android Engineer. Hands-on experience in Java, Kotlin, and Dart. Obsessed with Jetpack Compose! Travel Geek. Painting Lover. https://linktr.ee/mansik15