State Management in Jetpack Compose

Updated: Dec 12, 2021

What is state in jetpack compose?

A state is an object it can hold our data. If data changes happen, it will update all its subscribed UI widgets. If you want to update the data at runtime in your widgets, you can use the state object.


Stateful vs Stateless

State<T>

A type that holds a read-only value: It notifies the composition when value changes.

MutableState<T>

It's extension function of State. It allows us to update the value. When the value property is written to and changed, a recomposition of any subscribed RecomposeScopes will be scheduled. If value is written to with the same value, no recompositions will be scheduled.


Example:

var selectedIndex by mutableStateOf(0)
//selectedIndex = 5

No State

If we create the object without state, it doesn't update your UI when your data get changed.

@Composable
fun NoState() {
    var clickCount = 0
    Column {
        Button(onClick = {
            clickCount++
            Log.d("TAG", "NoState: "+clickCount)
        }) {
            Text(text = ""+clickCount+" times clicked")
        }
    }
}

Output:

When we press the button, onClick event triggered, but it doesn't update the count. But if you see the logcat, the value of this variable increased for each click.


Logcat output:

Why it doesn't update the UI?

It just changes the value of the variable, but our UI needs to refresh.

For auto UI refresh, we need state objects. If we use a state object, our UI will get refreshed automatically when data gets changed. Let's test the same code with the state object.


With State Object:

@Composable
fun MutableStateClick() {
    var clickCount by mutableStateOf(0)//Not recommended
    Column {
        Button(onClick = { clickCount++ }) {
            Text(text = "" + clickCount + " times clicked")
        }
    }
}

Output:

It works as expected. But it has some problems, if you use this state object with child composable it will not work. When you use this code, Android studio will give a warning and it recommended using it along with remember.


Remember:

The remember keyword can store a mutable or an immutable object. If value changes, it will trigger recomposition(refresh the UI) to update the widgets.


Syntax:

val currentValue = remember { mutableStateOf(0) } //Int
val userName = remember { mutableStateOf("") } //String

Example:

@Composable
fun RememberSample() {
    var clickCount by remember { mutableStateOf(0) }
    Column {
        Button(onClick = { clickCount++ }) {
            Text(text = "" + clickCount + " times clicked")
        }
    }
}

Remember works with child composable also. You can pass as an argument to your child composable function.


Drawback:

If your device orientation gets changed, the value will reset.


If you want to keep the data even if the activity recreated/orientation change happened, use "rememberSavable".


Remember Saveable:

Use rememberSaveable to restore your UI state after an activity or process is recreated. rememberSaveable retains state across recompositions. In addition, rememberSaveable also retains state across activity and process recreation.

@Composable
fun RememberSaveableSample() {
    var clickCount = rememberSaveable { mutableStateOf(0) }
    Column {
        Button(onClick = { clickCount.value++ }) {
            Text(text = "" + clickCount.value + " times clicked")
        }
    }
}

Output:




For State Hoisting, refer the official documentation:

https://developer.android.com/jetpack/compose/state Source code:

https://github.com/JetpackCompose/Jetpack-Compose-Samples/blob/master/JetPackComposeSamples/app/src/main/java/net/jetpackcompose/composetext/activities/ActivityStateManagement.kt



4,501 views0 comments

Recent Posts

See All

This site developed for Jetpack Compose tutorial. We will post tutorials frequently. You can also join our community by clicking login. 

  • Twitter
  • LinkedIn

You have any queries contact me. 

Subscribe for latest updates

Thanks for submitting!